Migrate tests to JUnit 5
Closes gh-959
This commit is contained in:
@@ -10,10 +10,15 @@ dependencies {
|
||||
|
||||
internal(platform(project(":spring-restdocs-platform")))
|
||||
|
||||
testImplementation("junit:junit")
|
||||
testImplementation("org.apache.pdfbox:pdfbox")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testImplementation("org.springframework:spring-core")
|
||||
|
||||
testRuntimeOnly("org.asciidoctor:asciidoctorj-pdf")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,11 +35,10 @@ import org.asciidoctor.Asciidoctor;
|
||||
import org.asciidoctor.Attributes;
|
||||
import org.asciidoctor.Options;
|
||||
import org.asciidoctor.SafeMode;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.util.FileSystemUtils;
|
||||
|
||||
@@ -51,42 +50,42 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Gerrit Meier
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractOperationBlockMacroTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temp = new TemporaryFolder();
|
||||
|
||||
private Options options;
|
||||
abstract class AbstractOperationBlockMacroTests {
|
||||
|
||||
private final Asciidoctor asciidoctor = Asciidoctor.Factory.create();
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
@TempDir
|
||||
protected File temp;
|
||||
|
||||
private Options options;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
prepareOperationSnippets(getBuildOutputLocation());
|
||||
this.options = Options.builder().safe(SafeMode.UNSAFE).baseDir(getSourceLocation()).build();
|
||||
this.options.setAttributes(getAttributes());
|
||||
CapturingLogHandler.clear();
|
||||
}
|
||||
|
||||
@After
|
||||
public void verifyLogging() {
|
||||
@AfterEach
|
||||
void verifyLogging() {
|
||||
assertThat(CapturingLogHandler.getLogRecords()).isEmpty();
|
||||
}
|
||||
|
||||
public void prepareOperationSnippets(File buildOutputLocation) throws IOException {
|
||||
private void prepareOperationSnippets(File buildOutputLocation) throws IOException {
|
||||
File destination = new File(buildOutputLocation, "generated-snippets/some-operation");
|
||||
destination.mkdirs();
|
||||
FileSystemUtils.copyRecursively(new File("src/test/resources/some-operation"), destination);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void codeBlockSnippetInclude() throws Exception {
|
||||
void codeBlockSnippetInclude() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets='curl-request']", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("snippet-simple"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void operationWithParameterizedName() throws Exception {
|
||||
void operationWithParameterizedName() throws Exception {
|
||||
Attributes attributes = getAttributes();
|
||||
attributes.setAttribute("name", "some");
|
||||
this.options.setAttributes(attributes);
|
||||
@@ -95,20 +94,20 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void codeBlockSnippetIncludeWithPdfBackend() throws Exception {
|
||||
void codeBlockSnippetIncludeWithPdfBackend() throws Exception {
|
||||
File output = configurePdfOutput();
|
||||
this.asciidoctor.convert("operation::some-operation[snippets='curl-request']", this.options);
|
||||
assertThat(extractStrings(output)).containsExactly("Curl request", "$ curl 'http://localhost:8080/' -i", "1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableSnippetInclude() throws Exception {
|
||||
void tableSnippetInclude() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets='response-fields']", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("snippet-table"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableSnippetIncludeWithPdfBackend() throws Exception {
|
||||
void tableSnippetIncludeWithPdfBackend() throws Exception {
|
||||
File output = configurePdfOutput();
|
||||
this.asciidoctor.convert("operation::some-operation[snippets='response-fields']", this.options);
|
||||
assertThat(extractStrings(output)).containsExactly("Response fields", "Path", "Type", "Description", "a",
|
||||
@@ -116,14 +115,14 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeSnippetInSection() throws Exception {
|
||||
void includeSnippetInSection() throws Exception {
|
||||
String result = this.asciidoctor.convert("= A\n:doctype: book\n:sectnums:\n\nAlpha\n\n== B\n\nBravo\n\n"
|
||||
+ "operation::some-operation[snippets='curl-request']\n\n== C\n", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("snippet-in-section"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeSnippetInSectionWithAbsoluteLevelOffset() throws Exception {
|
||||
void includeSnippetInSectionWithAbsoluteLevelOffset() throws Exception {
|
||||
String result = this.asciidoctor
|
||||
.convert("= A\n:doctype: book\n:sectnums:\n:leveloffset: 1\n\nAlpha\n\n= B\n\nBravo\n\n"
|
||||
+ "operation::some-operation[snippets='curl-request']\n\n= C\n", this.options);
|
||||
@@ -131,7 +130,7 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeSnippetInSectionWithRelativeLevelOffset() throws Exception {
|
||||
void includeSnippetInSectionWithRelativeLevelOffset() throws Exception {
|
||||
String result = this.asciidoctor
|
||||
.convert("= A\n:doctype: book\n:sectnums:\n:leveloffset: +1\n\nAlpha\n\n= B\n\nBravo\n\n"
|
||||
+ "operation::some-operation[snippets='curl-request']\n\n= C\n", this.options);
|
||||
@@ -139,7 +138,7 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeSnippetInSectionWithPdfBackend() throws Exception {
|
||||
void includeSnippetInSectionWithPdfBackend() throws Exception {
|
||||
File output = configurePdfOutput();
|
||||
this.asciidoctor.convert("== Section\n" + "operation::some-operation[snippets='curl-request']", this.options);
|
||||
assertThat(extractStrings(output)).containsExactly("Section", "Curl request",
|
||||
@@ -147,26 +146,26 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeMultipleSnippets() throws Exception {
|
||||
void includeMultipleSnippets() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets='curl-request,http-request']",
|
||||
this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("multiple-snippets"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useMacroWithoutSnippetAttributeAddsAllSnippets() throws Exception {
|
||||
void useMacroWithoutSnippetAttributeAddsAllSnippets() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[]", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("all-snippets"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useMacroWithEmptySnippetAttributeAddsAllSnippets() throws Exception {
|
||||
void useMacroWithEmptySnippetAttributeAddsAllSnippets() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets=]", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("all-snippets"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includingMissingSnippetAddsWarning() throws Exception {
|
||||
void includingMissingSnippetAddsWarning() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets='missing-snippet']", this.options);
|
||||
assertThat(result).startsWith(getExpectedContentFromFile("missing-snippet"));
|
||||
assertThat(CapturingLogHandler.getLogRecords()).hasSize(1);
|
||||
@@ -177,13 +176,13 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultTitleIsProvidedForCustomSnippet() throws Exception {
|
||||
void defaultTitleIsProvidedForCustomSnippet() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::some-operation[snippets='custom-snippet']", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("custom-snippet-default-title"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOperationIsHandledGracefully() throws Exception {
|
||||
void missingOperationIsHandledGracefully() throws Exception {
|
||||
String result = this.asciidoctor.convert("operation::missing-operation[]", this.options);
|
||||
assertThat(result).startsWith(getExpectedContentFromFile("missing-operation"));
|
||||
assertThat(CapturingLogHandler.getLogRecords()).hasSize(1);
|
||||
@@ -194,14 +193,14 @@ public abstract class AbstractOperationBlockMacroTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void titleOfBuiltInSnippetCanBeCustomizedUsingDocumentAttribute() throws URISyntaxException, IOException {
|
||||
void titleOfBuiltInSnippetCanBeCustomizedUsingDocumentAttribute() throws URISyntaxException, IOException {
|
||||
String result = this.asciidoctor.convert(":operation-curl-request-title: Example request\n"
|
||||
+ "operation::some-operation[snippets='curl-request']", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("built-in-snippet-custom-title"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void titleOfCustomSnippetCanBeCustomizedUsingDocumentAttribute() throws Exception {
|
||||
void titleOfCustomSnippetCanBeCustomizedUsingDocumentAttribute() throws Exception {
|
||||
String result = this.asciidoctor.convert(":operation-custom-snippet-title: Customized title\n"
|
||||
+ "operation::some-operation[snippets='custom-snippet']", this.options);
|
||||
assertThat(result).isEqualTo(getExpectedContentFromFile("custom-snippet-custom-title"));
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.io.File;
|
||||
import org.asciidoctor.Asciidoctor;
|
||||
import org.asciidoctor.Attributes;
|
||||
import org.asciidoctor.Options;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -30,23 +30,23 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class DefaultAttributesPreprocessorTests {
|
||||
class DefaultAttributesPreprocessorTests {
|
||||
|
||||
@Test
|
||||
public void snippetsAttributeIsSet() {
|
||||
void snippetsAttributeIsSet() {
|
||||
String converted = createAsciidoctor().convert("{snippets}", createOptions("projectdir=../../.."));
|
||||
assertThat(converted).contains("build" + File.separatorChar + "generated-snippets");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snippetsAttributeFromConvertArgumentIsNotOverridden() {
|
||||
void snippetsAttributeFromConvertArgumentIsNotOverridden() {
|
||||
String converted = createAsciidoctor().convert("{snippets}",
|
||||
createOptions("snippets=custom projectdir=../../.."));
|
||||
assertThat(converted).contains("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snippetsAttributeFromDocumentPreambleIsNotOverridden() {
|
||||
void snippetsAttributeFromDocumentPreambleIsNotOverridden() {
|
||||
String converted = createAsciidoctor().convert(":snippets: custom\n{snippets}",
|
||||
createOptions("projectdir=../../.."));
|
||||
assertThat(converted).contains("custom");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,47 +19,42 @@ package org.springframework.restdocs.asciidoctor;
|
||||
import java.io.File;
|
||||
|
||||
import org.asciidoctor.Attributes;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.junit.jupiter.params.ParameterizedClass;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
/**
|
||||
* Tests for Ruby operation block macro when used in a Gradle build.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GradleOperationBlockMacroTests extends AbstractOperationBlockMacroTests {
|
||||
@ParameterizedClass
|
||||
@ValueSource(strings = { "projectdir", "gradle-projectdir" })
|
||||
class GradleOperationBlockMacroTests extends AbstractOperationBlockMacroTests {
|
||||
|
||||
private final String attributeName;
|
||||
|
||||
public GradleOperationBlockMacroTests(String attributeName) {
|
||||
GradleOperationBlockMacroTests(String attributeName) {
|
||||
this.attributeName = attributeName;
|
||||
}
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Object[] parameters() {
|
||||
return new Object[] { "projectdir", "gradle-projectdir" };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attributes getAttributes() {
|
||||
Attributes attributes = Attributes.builder()
|
||||
.attribute(this.attributeName, new File(this.temp.getRoot(), "gradle-project").getAbsolutePath())
|
||||
.attribute(this.attributeName, new File(this.temp, "gradle-project").getAbsolutePath())
|
||||
.build();
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getBuildOutputLocation() {
|
||||
File outputLocation = new File(this.temp.getRoot(), "gradle-project/build");
|
||||
File outputLocation = new File(this.temp, "gradle-project/build");
|
||||
outputLocation.mkdirs();
|
||||
return outputLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getSourceLocation() {
|
||||
File sourceLocation = new File(this.temp.getRoot(), "gradle-project/src/docs/asciidoc");
|
||||
File sourceLocation = new File(this.temp, "gradle-project/src/docs/asciidoc");
|
||||
if (!sourceLocation.exists()) {
|
||||
sourceLocation.mkdirs();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2021 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,23 +20,23 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.asciidoctor.Attributes;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
/**
|
||||
* Tests for Ruby operation block macro when used in a Maven build.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class MavenOperationBlockMacroTests extends AbstractOperationBlockMacroTests {
|
||||
class MavenOperationBlockMacroTests extends AbstractOperationBlockMacroTests {
|
||||
|
||||
@Before
|
||||
public void setMavenHome() {
|
||||
@BeforeEach
|
||||
void setMavenHome() {
|
||||
System.setProperty("maven.home", "maven-home");
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearMavenHome() {
|
||||
@AfterEach
|
||||
void clearMavenHome() {
|
||||
System.clearProperty("maven.home");
|
||||
}
|
||||
|
||||
@@ -55,14 +55,14 @@ public class MavenOperationBlockMacroTests extends AbstractOperationBlockMacroTe
|
||||
|
||||
@Override
|
||||
protected File getBuildOutputLocation() {
|
||||
File outputLocation = new File(this.temp.getRoot(), "maven-project/target");
|
||||
File outputLocation = new File(this.temp, "maven-project/target");
|
||||
outputLocation.mkdirs();
|
||||
return outputLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File getSourceLocation() {
|
||||
File sourceLocation = new File(this.temp.getRoot(), "maven-project/src/main/asciidoc");
|
||||
File sourceLocation = new File(this.temp, "maven-project/src/main/asciidoc");
|
||||
if (!sourceLocation.exists()) {
|
||||
sourceLocation.mkdirs();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,9 +21,8 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
@@ -35,23 +34,23 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*/
|
||||
public class SnippetsDirectoryResolverTests {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
@Test
|
||||
public void mavenProjectsUseTargetGeneratedSnippets() throws IOException {
|
||||
this.temporaryFolder.newFile("pom.xml");
|
||||
new File(this.temp, "pom.xml").createNewFile();
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("docdir", new File(this.temporaryFolder.getRoot(), "src/main/asciidoc").getAbsolutePath());
|
||||
attributes.put("docdir", new File(this.temp, "src/main/asciidoc").getAbsolutePath());
|
||||
File snippetsDirectory = getMavenSnippetsDirectory(attributes);
|
||||
assertThat(snippetsDirectory).isAbsolute();
|
||||
assertThat(snippetsDirectory).isEqualTo(new File(this.temporaryFolder.getRoot(), "target/generated-snippets"));
|
||||
assertThat(snippetsDirectory).isEqualTo(new File(this.temp, "target/generated-snippets"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void illegalStateExceptionWhenMavenPomCannotBeFound() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
String docdir = new File(this.temporaryFolder.getRoot(), "src/main/asciidoc").getAbsolutePath();
|
||||
String docdir = new File(this.temp, "src/main/asciidoc").getAbsolutePath();
|
||||
attributes.put("docdir", docdir);
|
||||
assertThatIllegalStateException().isThrownBy(() -> getMavenSnippetsDirectory(attributes))
|
||||
.withMessage("pom.xml not found in '" + docdir + "' or above");
|
||||
|
||||
@@ -32,6 +32,8 @@ task jmustacheRepackJar(type: Jar) { repackJar ->
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.apiguardian:apiguardian-api")
|
||||
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
implementation("org.springframework:spring-web")
|
||||
implementation(files(jmustacheRepackJar))
|
||||
@@ -50,21 +52,29 @@ dependencies {
|
||||
optional("org.junit.jupiter:junit-jupiter-api")
|
||||
|
||||
testFixturesApi(platform(project(":spring-restdocs-platform")))
|
||||
testFixturesApi("junit:junit")
|
||||
testFixturesApi("org.assertj:assertj-core")
|
||||
testFixturesApi("org.hamcrest:hamcrest-core")
|
||||
testFixturesApi("org.junit.jupiter:junit-jupiter")
|
||||
testFixturesApi("org.mockito:mockito-core")
|
||||
|
||||
testFixturesCompileOnly("org.apiguardian:apiguardian-api")
|
||||
|
||||
testFixturesImplementation(files(jmustacheRepackJar))
|
||||
testFixturesImplementation("org.hamcrest:hamcrest-library")
|
||||
testFixturesImplementation("org.mockito:mockito-core")
|
||||
testFixturesImplementation("org.springframework:spring-core")
|
||||
testFixturesImplementation("org.springframework:spring-web")
|
||||
|
||||
testFixturesRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
|
||||
testCompileOnly("org.apiguardian:apiguardian-api")
|
||||
|
||||
testImplementation("junit:junit")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.javamoney:moneta")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
testImplementation("org.springframework:spring-test")
|
||||
|
||||
testRuntimeOnly("org.apache.tomcat.embed:tomcat-embed-el")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-engine")
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -81,3 +91,7 @@ components.java.withVariantsFromConfiguration(configurations.testFixturesApiElem
|
||||
components.java.withVariantsFromConfiguration(configurations.testFixturesRuntimeElements) {
|
||||
skip()
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,9 +74,9 @@ public abstract class TemplatedSnippet implements Snippet {
|
||||
RestDocumentationContext context = (RestDocumentationContext) operation.getAttributes()
|
||||
.get(RestDocumentationContext.class.getName());
|
||||
WriterResolver writerResolver = (WriterResolver) operation.getAttributes().get(WriterResolver.class.getName());
|
||||
Map<String, Object> model = createModel(operation);
|
||||
model.putAll(this.attributes);
|
||||
try (Writer writer = writerResolver.resolve(operation.getName(), this.snippetName, context)) {
|
||||
Map<String, Object> model = createModel(operation);
|
||||
model.putAll(this.attributes);
|
||||
TemplateEngine templateEngine = (TemplateEngine) operation.getAttributes()
|
||||
.get(TemplateEngine.class.getName());
|
||||
writer.append(templateEngine.compileTemplate(this.templateName).render(model));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2021 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,25 +16,16 @@
|
||||
|
||||
package org.springframework.restdocs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.GeneratedSnippets;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.CodeBlockCondition;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.HttpRequestCondition;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.HttpResponseCondition;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.TableCondition;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
/**
|
||||
@@ -42,28 +33,11 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public abstract class AbstractSnippetTests {
|
||||
|
||||
protected final TemplateFormat templateFormat;
|
||||
protected final TemplateFormat templateFormat = TemplateFormats.asciidoctor();
|
||||
|
||||
@Rule
|
||||
public GeneratedSnippets generatedSnippets;
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder;
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static List<Object[]> parameters() {
|
||||
return Arrays.asList(new Object[] { "Asciidoctor", TemplateFormats.asciidoctor() },
|
||||
new Object[] { "Markdown", TemplateFormats.markdown() });
|
||||
}
|
||||
|
||||
protected AbstractSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
this.generatedSnippets = new GeneratedSnippets(templateFormat);
|
||||
this.templateFormat = templateFormat;
|
||||
this.operationBuilder = new OperationBuilder(this.templateFormat);
|
||||
}
|
||||
protected AssertableSnippets snippets;
|
||||
|
||||
public CodeBlockCondition<?> codeBlock(String language) {
|
||||
return this.codeBlock(language, null);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
@@ -55,7 +55,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
* @author Andy Wilkinson
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class RestDocumentationGeneratorTests {
|
||||
class RestDocumentationGeneratorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final RequestConverter<Object> requestConverter = mock(RequestConverter.class);
|
||||
@@ -80,7 +80,7 @@ public class RestDocumentationGeneratorTests {
|
||||
private final OperationPreprocessor responsePreprocessor = mock(OperationPreprocessor.class);
|
||||
|
||||
@Test
|
||||
public void basicHandling() throws IOException {
|
||||
void basicHandling() throws IOException {
|
||||
given(this.requestConverter.convert(this.request)).willReturn(this.operationRequest);
|
||||
given(this.responseConverter.convert(this.response)).willReturn(this.operationResponse);
|
||||
HashMap<String, Object> configuration = new HashMap<>();
|
||||
@@ -90,7 +90,7 @@ public class RestDocumentationGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultSnippetsAreCalled() throws IOException {
|
||||
void defaultSnippetsAreCalled() throws IOException {
|
||||
given(this.requestConverter.convert(this.request)).willReturn(this.operationRequest);
|
||||
given(this.responseConverter.convert(this.response)).willReturn(this.operationResponse);
|
||||
HashMap<String, Object> configuration = new HashMap<>();
|
||||
@@ -107,7 +107,7 @@ public class RestDocumentationGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultOperationRequestPreprocessorsAreCalled() throws IOException {
|
||||
void defaultOperationRequestPreprocessorsAreCalled() throws IOException {
|
||||
given(this.requestConverter.convert(this.request)).willReturn(this.operationRequest);
|
||||
given(this.responseConverter.convert(this.response)).willReturn(this.operationResponse);
|
||||
HashMap<String, Object> configuration = new HashMap<>();
|
||||
@@ -128,7 +128,7 @@ public class RestDocumentationGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultOperationResponsePreprocessorsAreCalled() throws IOException {
|
||||
void defaultOperationResponsePreprocessorsAreCalled() throws IOException {
|
||||
given(this.requestConverter.convert(this.request)).willReturn(this.operationRequest);
|
||||
given(this.responseConverter.convert(this.response)).willReturn(this.operationResponse);
|
||||
HashMap<String, Object> configuration = new HashMap<>();
|
||||
@@ -149,7 +149,7 @@ public class RestDocumentationGeneratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newGeneratorOnlyCallsItsSnippets() throws IOException {
|
||||
void newGeneratorOnlyCallsItsSnippets() throws IOException {
|
||||
OperationRequestPreprocessor requestPreprocessor = mock(OperationRequestPreprocessor.class);
|
||||
OperationResponsePreprocessor responsePreprocessor = mock(OperationResponsePreprocessor.class);
|
||||
given(this.requestConverter.convert(this.request)).willReturn(this.operationRequest);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.cli;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -29,27 +29,27 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Tomasz Kopczynski
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ConcatenatingCommandFormatterTests {
|
||||
class ConcatenatingCommandFormatterTests {
|
||||
|
||||
private CommandFormatter singleLineFormat = new ConcatenatingCommandFormatter(" ");
|
||||
|
||||
@Test
|
||||
public void formattingAnEmptyListProducesAnEmptyString() {
|
||||
void formattingAnEmptyListProducesAnEmptyString() {
|
||||
assertThat(this.singleLineFormat.format(Collections.<String>emptyList())).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formattingNullProducesAnEmptyString() {
|
||||
void formattingNullProducesAnEmptyString() {
|
||||
assertThat(this.singleLineFormat.format(null)).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formattingASingleElement() {
|
||||
void formattingASingleElement() {
|
||||
assertThat(this.singleLineFormat.format(Collections.singletonList("alpha"))).isEqualTo(" alpha");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formattingMultipleElements() {
|
||||
void formattingMultipleElements() {
|
||||
assertThat(this.singleLineFormat.format(Arrays.asList("alpha", "bravo"))).isEqualTo(" alpha bravo");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,11 @@ package org.springframework.restdocs.cli;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -40,200 +37,209 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Paul-Christian Volkmer
|
||||
* @author Tomasz Kopczynski
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
||||
class CurlRequestSnippetTests {
|
||||
|
||||
private CommandFormatter commandFormatter = CliDocumentation.singleLineFormat();
|
||||
|
||||
public CurlRequestSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET"));
|
||||
.document(operationBuilder.request("http://localhost/foo").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ curl 'http://localhost/foo' -i -X GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonGetRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void nonGetRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ curl 'http://localhost/foo' -i -X POST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithContent(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").content("content").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET -d 'content'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").content("content").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X GET -d 'content'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param=value").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X GET"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param=value").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo?param=value' -i -X GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryStringWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param' -i -X GET"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ curl 'http://localhost/foo?param' -i -X GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param=value").method("POST").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param=value' -i -X POST"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param=value").method("POST").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo?param=value' -i -X POST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithQueryStringWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithQueryStringWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param").method("POST").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?param' -i -X POST"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param").method("POST").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo?param' -i -X POST"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithOneParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithOneParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=v1").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").content("k1=v1").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithOneParameterAndExplicitContentType() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithOneParameterAndExplicitContentType(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.method("POST")
|
||||
.content("k1=v1")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X POST -d 'k1=v1'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithOneParameterWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1='"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").content("k1=").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X POST -d 'k1='"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithMultipleParameters() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithMultipleParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.content("k1=v1&k1=v1-bis&k2=v2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
||||
.withContent("$ curl 'http://localhost/foo' -i -X POST" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X POST" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithUrlEncodedParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithUrlEncodedParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content("k1=a%26b").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").content("k1=a%26b").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X POST -d 'k1=a%26b'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithJsonData() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithJsonData(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.content("{\"a\":\"alpha\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(
|
||||
"$ curl 'http://localhost/foo' -i -X POST -H 'Content-Type: application/json' -d '{\"a\":\"alpha\"}'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content(
|
||||
"$ curl 'http://localhost/foo' -i -X POST -H 'Content-Type: application/json' -d '{\"a\":\"alpha\"}'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithOneParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithOneParameter(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=v1").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("PUT").content("k1=v1").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=v1'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithMultipleParameters() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithMultipleParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("PUT")
|
||||
.content("k1=v1&k1=v1-bis&k2=v2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
||||
.withContent("$ curl 'http://localhost/foo' -i -X PUT" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X PUT" + " -d 'k1=v1&k1=v1-bis&k2=v2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithUrlEncodedParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithUrlEncodedParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("PUT").content("k1=a%26b").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("PUT").content("k1=a%26b").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X PUT -d 'k1=a%26b'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void requestWithHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(
|
||||
"$ curl 'http://localhost/foo' -i -X GET" + " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X GET" + " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeadersMultiline() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithHeadersMultiline(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(CliDocumentation.multiLineFormat())
|
||||
.document(this.operationBuilder.request("http://localhost/foo")
|
||||
.document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent(String.format("$ curl 'http://localhost/foo' -i -X GET \\%n"
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content(String.format("$ curl 'http://localhost/foo' -i -X GET \\%n"
|
||||
+ " -H 'Content-Type: application/json' \\%n" + " -H 'a: alpha'")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithCookies() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void requestWithCookies(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.cookie("name1", "value1")
|
||||
.cookie("name2", "value2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash")
|
||||
.withContent("$ curl 'http://localhost/foo' -i -X GET" + " --cookie 'name1=value1;name2=value2'"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X GET" + " --cookie 'name1=value1;name2=value2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithNoSubmittedFileName() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithNoSubmittedFileName(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("metadata", "{\"description\": \"foo\"}".getBytes())
|
||||
.build());
|
||||
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
|
||||
+ "'Content-Type: multipart/form-data' -F " + "'metadata={\"description\": \"foo\"}'";
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.curlRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithContentType() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithContentType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
@@ -242,12 +248,13 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
||||
.build());
|
||||
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
|
||||
+ "'Content-Type: multipart/form-data' -F " + "'image=@documents/images/example.png;type=image/png'";
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.curlRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPost() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPost(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
@@ -255,36 +262,38 @@ public class CurlRequestSnippetTests extends AbstractSnippetTests {
|
||||
.build());
|
||||
String expectedContent = "$ curl 'http://localhost/upload' -i -X POST -H "
|
||||
+ "'Content-Type: multipart/form-data' -F " + "'image=@documents/images/example.png'";
|
||||
assertThat(this.generatedSnippets.curlRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.curlRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthCredentialsAreSuppliedUsingUserOption() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void basicAuthCredentialsAreSuppliedUsingUserOption(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString("user:secret".getBytes()))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -u 'user:secret' -X GET"));
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -u 'user:secret' -X GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAttributes() throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void customAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.HOST, "api.example.com")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo' -i -X GET -H 'Host: api.example.com'"
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo' -i -X GET -H 'Host: api.example.com'"
|
||||
+ " -H 'Content-Type: application/json' -H 'a: alpha'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void deleteWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new CurlRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(this.generatedSnippets.curlRequest())
|
||||
.is(codeBlock("bash").withContent("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X DELETE"));
|
||||
.document(operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(snippets.curlRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ curl 'http://localhost/foo?a=alpha&b=bravo' -i " + "-X DELETE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,11 @@ package org.springframework.restdocs.cli;
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -41,249 +38,257 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Raman Gupta
|
||||
* @author Tomasz Kopczynski
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class HttpieRequestSnippetTests extends AbstractSnippetTests {
|
||||
class HttpieRequestSnippetTests {
|
||||
|
||||
private CommandFormatter commandFormatter = CliDocumentation.singleLineFormat();
|
||||
|
||||
public HttpieRequestSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").build());
|
||||
assertThat(snippets.httpieRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content("$ http GET 'http://localhost/foo'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonGetRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void nonGetRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http POST 'http://localhost/foo'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").build());
|
||||
assertThat(snippets.httpieRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content("$ http POST 'http://localhost/foo'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithContent(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo").content("content").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ echo 'content' | http GET 'http://localhost/foo'"));
|
||||
.document(operationBuilder.request("http://localhost/foo").content("content").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ echo 'content' | http GET 'http://localhost/foo'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param=value").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param=value'"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param=value").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ http GET 'http://localhost/foo?param=value'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryStringWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo?param'"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ http GET 'http://localhost/foo?param'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param=value").method("POST").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http POST 'http://localhost/foo?param=value'"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param=value").method("POST").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http POST 'http://localhost/foo?param=value'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithQueryStringWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithQueryStringWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?param").method("POST").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http POST 'http://localhost/foo?param'"));
|
||||
.document(operationBuilder.request("http://localhost/foo?param").method("POST").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguage("bash").content("$ http POST 'http://localhost/foo?param'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithOneParameter() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithOneParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=v1")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form POST 'http://localhost/foo' 'k1=v1'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithOneParameterWithNoValue() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithOneParameterWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1='"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form POST 'http://localhost/foo' 'k1='"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithMultipleParameters() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithMultipleParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=v1&k1=v1-bis&k2=v2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form POST 'http://localhost/foo' 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithUrlEncodedParameter() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithUrlEncodedParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=a%26b")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form POST 'http://localhost/foo' 'k1=a&b'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form POST 'http://localhost/foo' 'k1=a&b'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithOneParameter() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithOneParameter(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("PUT")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=v1")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=v1'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form PUT 'http://localhost/foo' 'k1=v1'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithMultipleParameters() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithMultipleParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("PUT")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=v1&k1=v1-bis&k2=v2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
||||
.withContent("$ http --form PUT 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form PUT 'http://localhost/foo'" + " 'k1=v1' 'k1=v1-bis' 'k2=v2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithUrlEncodedParameter() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithUrlEncodedParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.method("PUT")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.content("k1=a%26b")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --form PUT 'http://localhost/foo' 'k1=a&b'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --form PUT 'http://localhost/foo' 'k1=a&b'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void requestWithHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
||||
.withContent("$ http GET 'http://localhost/foo'" + " 'Content-Type:application/json' 'a:alpha'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content(("$ http GET 'http://localhost/foo'" + " 'Content-Type:application/json' 'a:alpha'")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeadersMultiline() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithHeadersMultiline(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(CliDocumentation.multiLineFormat())
|
||||
.document(this.operationBuilder.request("http://localhost/foo")
|
||||
.document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(String.format(
|
||||
"$ http GET 'http://localhost/foo' \\%n" + " 'Content-Type:application/json' \\%n 'a:alpha'")));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content(String.format("$ http GET 'http://localhost/foo' \\%n"
|
||||
+ " 'Content-Type:application/json' \\%n 'a:alpha'")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithCookies() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void requestWithCookies(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.cookie("name1", "value1")
|
||||
.cookie("name2", "value2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash")
|
||||
.withContent("$ http GET 'http://localhost/foo'" + " 'Cookie:name1=value1' 'Cookie:name2=value2'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content(("$ http GET 'http://localhost/foo'" + " 'Cookie:name1=value1' 'Cookie:name2=value2'")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithNoSubmittedFileName() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("metadata", "{\"description\": \"foo\"}".getBytes())
|
||||
.build());
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithNoSubmittedFileName(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("metadata", "{\"description\": \"foo\"}".getBytes())
|
||||
.build());
|
||||
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
|
||||
+ " 'metadata'='{\"description\": \"foo\"}'";
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.httpieRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithContentType() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE)
|
||||
.submittedFileName("documents/images/example.png")
|
||||
.build());
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithContentType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE)
|
||||
.submittedFileName("documents/images/example.png")
|
||||
.build());
|
||||
// httpie does not yet support manually set content type by part
|
||||
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
|
||||
+ " 'image'@'documents/images/example.png'";
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.httpieRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPost() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
.submittedFileName("documents/images/example.png")
|
||||
.build());
|
||||
@RenderedSnippetTest
|
||||
void multipartPost(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", new byte[0])
|
||||
.submittedFileName("documents/images/example.png")
|
||||
.build());
|
||||
String expectedContent = "$ http --multipart POST 'http://localhost/upload'"
|
||||
+ " 'image'@'documents/images/example.png'";
|
||||
assertThat(this.generatedSnippets.httpieRequest()).is(codeBlock("bash").withContent(expectedContent));
|
||||
assertThat(snippets.httpieRequest())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash").content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicAuthCredentialsAreSuppliedUsingAuthOption() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void basicAuthCredentialsAreSuppliedUsingAuthOption(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString("user:secret".getBytes()))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http --auth 'user:secret' GET 'http://localhost/foo'"));
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http --auth 'user:secret' GET 'http://localhost/foo'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customAttributes() throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void customAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter).document(operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.HOST, "api.example.com")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http GET 'http://localhost/foo' 'Host:api.example.com'"
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http GET 'http://localhost/foo' 'Host:api.example.com'"
|
||||
+ " 'Content-Type:application/json' 'a:alpha'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void deleteWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpieRequestSnippet(this.commandFormatter)
|
||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(this.generatedSnippets.httpieRequest())
|
||||
.is(codeBlock("bash").withContent("$ http DELETE 'http://localhost/foo?a=alpha&b=bravo'"));
|
||||
.document(operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(snippets.httpieRequest()).isCodeBlock((codeBlock) -> codeBlock.withLanguage("bash")
|
||||
.content("$ http DELETE 'http://localhost/foo?a=alpha&b=bravo'"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -63,13 +63,13 @@ import static org.mockito.Mockito.mock;
|
||||
* @author Andy Wilkinson
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class RestDocumentationConfigurerTests {
|
||||
class RestDocumentationConfigurerTests {
|
||||
|
||||
private final TestRestDocumentationConfigurer configurer = new TestRestDocumentationConfigurer();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
void defaultConfiguration() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.apply(configuration, createContext());
|
||||
assertThat(configuration).containsKey(TemplateEngine.class.getName());
|
||||
@@ -102,7 +102,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customTemplateEngine() {
|
||||
void customTemplateEngine() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
TemplateEngine templateEngine = mock(TemplateEngine.class);
|
||||
this.configurer.templateEngine(templateEngine).apply(configuration, createContext());
|
||||
@@ -110,7 +110,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customWriterResolver() {
|
||||
void customWriterResolver() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
WriterResolver writerResolver = mock(WriterResolver.class);
|
||||
this.configurer.writerResolver(writerResolver).apply(configuration, createContext());
|
||||
@@ -118,7 +118,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customDefaultSnippets() {
|
||||
void customDefaultSnippets() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.snippets().withDefaults(CliDocumentation.curlRequest()).apply(configuration, createContext());
|
||||
assertThat(configuration).containsKey(RestDocumentationGenerator.ATTRIBUTE_NAME_DEFAULT_SNIPPETS);
|
||||
@@ -133,7 +133,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void additionalDefaultSnippets() {
|
||||
void additionalDefaultSnippets() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
Snippet snippet = mock(Snippet.class);
|
||||
this.configurer.snippets().withAdditionalDefaults(snippet).apply(configuration, createContext());
|
||||
@@ -148,7 +148,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetEncoding() {
|
||||
void customSnippetEncoding() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.snippets().withEncoding("ISO-8859-1");
|
||||
this.configurer.apply(configuration, createContext());
|
||||
@@ -162,7 +162,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customTemplateFormat() {
|
||||
void customTemplateFormat() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.snippets().withTemplateFormat(TemplateFormats.markdown()).apply(configuration, createContext());
|
||||
assertThat(configuration).containsKey(SnippetConfiguration.class.getName());
|
||||
@@ -174,7 +174,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void asciidoctorTableCellContentLambaIsInstalledWhenUsingAsciidoctorTemplateFormat() {
|
||||
void asciidoctorTableCellContentLambaIsInstalledWhenUsingAsciidoctorTemplateFormat() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.apply(configuration, createContext());
|
||||
TemplateEngine templateEngine = (TemplateEngine) configuration.get(TemplateEngine.class.getName());
|
||||
@@ -187,7 +187,7 @@ public class RestDocumentationConfigurerTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void asciidoctorTableCellContentLambaIsNotInstalledWhenUsingNonAsciidoctorTemplateFormat() {
|
||||
void asciidoctorTableCellContentLambaIsNotInstalledWhenUsingNonAsciidoctorTemplateFormat() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.snippetConfigurer.withTemplateFormat(TemplateFormats.markdown());
|
||||
this.configurer.apply(configuration, createContext());
|
||||
@@ -199,7 +199,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customDefaultOperationRequestPreprocessor() {
|
||||
void customDefaultOperationRequestPreprocessor() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.operationPreprocessors()
|
||||
.withRequestDefaults(Preprocessors.prettyPrint(), Preprocessors.modifyHeaders().remove("Foo"))
|
||||
@@ -214,7 +214,7 @@ public class RestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customDefaultOperationResponsePreprocessor() {
|
||||
void customDefaultOperationResponsePreprocessor() {
|
||||
Map<String, Object> configuration = new HashMap<>();
|
||||
this.configurer.operationPreprocessors()
|
||||
.withResponseDefaults(Preprocessors.prettyPrint(), Preprocessors.modifyHeaders().remove("Foo"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.constraints;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
@@ -30,7 +30,7 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ConstraintDescriptionsTests {
|
||||
class ConstraintDescriptionsTests {
|
||||
|
||||
private final ConstraintResolver constraintResolver = mock(ConstraintResolver.class);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ConstraintDescriptionsTests {
|
||||
this.constraintResolver, this.constraintDescriptionResolver);
|
||||
|
||||
@Test
|
||||
public void descriptionsForConstraints() {
|
||||
void descriptionsForConstraints() {
|
||||
Constraint constraint1 = new Constraint("constraint1", Collections.<String, Object>emptyMap());
|
||||
Constraint constraint2 = new Constraint("constraint2", Collections.<String, Object>emptyMap());
|
||||
given(this.constraintResolver.resolveForProperty("foo", Constrained.class))
|
||||
@@ -52,7 +52,7 @@ public class ConstraintDescriptionsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyListOfDescriptionsWhenThereAreNoConstraints() {
|
||||
void emptyListOfDescriptionsWhenThereAreNoConstraints() {
|
||||
given(this.constraintResolver.resolveForProperty("foo", Constrained.class))
|
||||
.willReturn(Collections.<Constraint>emptyList());
|
||||
assertThat(this.constraintDescriptions.descriptionsForProperty("foo").size()).isEqualTo(0);
|
||||
|
||||
@@ -60,7 +60,7 @@ import org.hibernate.validator.constraints.LuhnCheck;
|
||||
import org.hibernate.validator.constraints.Mod10Check;
|
||||
import org.hibernate.validator.constraints.Mod11Check;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@@ -77,183 +77,183 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResourceBundleConstraintDescriptionResolverTests {
|
||||
class ResourceBundleConstraintDescriptionResolverTests {
|
||||
|
||||
private final ResourceBundleConstraintDescriptionResolver resolver = new ResourceBundleConstraintDescriptionResolver();
|
||||
|
||||
@Test
|
||||
public void defaultMessageAssertFalse() {
|
||||
void defaultMessageAssertFalse() {
|
||||
assertThat(constraintDescriptionForField("assertFalse")).isEqualTo("Must be false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageAssertTrue() {
|
||||
void defaultMessageAssertTrue() {
|
||||
assertThat(constraintDescriptionForField("assertTrue")).isEqualTo("Must be true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageCodePointLength() {
|
||||
void defaultMessageCodePointLength() {
|
||||
assertThat(constraintDescriptionForField("codePointLength"))
|
||||
.isEqualTo("Code point length must be between 2 and 5 inclusive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageCurrency() {
|
||||
void defaultMessageCurrency() {
|
||||
assertThat(constraintDescriptionForField("currency"))
|
||||
.isEqualTo("Must be in an accepted currency unit (GBP, USD)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageDecimalMax() {
|
||||
void defaultMessageDecimalMax() {
|
||||
assertThat(constraintDescriptionForField("decimalMax")).isEqualTo("Must be at most 9.875");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageDecimalMin() {
|
||||
void defaultMessageDecimalMin() {
|
||||
assertThat(constraintDescriptionForField("decimalMin")).isEqualTo("Must be at least 1.5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageDigits() {
|
||||
void defaultMessageDigits() {
|
||||
assertThat(constraintDescriptionForField("digits"))
|
||||
.isEqualTo("Must have at most 2 integral digits and 5 fractional digits");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageFuture() {
|
||||
void defaultMessageFuture() {
|
||||
assertThat(constraintDescriptionForField("future")).isEqualTo("Must be in the future");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageFutureOrPresent() {
|
||||
void defaultMessageFutureOrPresent() {
|
||||
assertThat(constraintDescriptionForField("futureOrPresent")).isEqualTo("Must be in the future or the present");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageMax() {
|
||||
void defaultMessageMax() {
|
||||
assertThat(constraintDescriptionForField("max")).isEqualTo("Must be at most 10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageMin() {
|
||||
void defaultMessageMin() {
|
||||
assertThat(constraintDescriptionForField("min")).isEqualTo("Must be at least 10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNotNull() {
|
||||
void defaultMessageNotNull() {
|
||||
assertThat(constraintDescriptionForField("notNull")).isEqualTo("Must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNull() {
|
||||
void defaultMessageNull() {
|
||||
assertThat(constraintDescriptionForField("nul")).isEqualTo("Must be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessagePast() {
|
||||
void defaultMessagePast() {
|
||||
assertThat(constraintDescriptionForField("past")).isEqualTo("Must be in the past");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessagePastOrPresent() {
|
||||
void defaultMessagePastOrPresent() {
|
||||
assertThat(constraintDescriptionForField("pastOrPresent")).isEqualTo("Must be in the past or the present");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessagePattern() {
|
||||
void defaultMessagePattern() {
|
||||
assertThat(constraintDescriptionForField("pattern"))
|
||||
.isEqualTo("Must match the regular expression `[A-Z][a-z]+`");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageSize() {
|
||||
void defaultMessageSize() {
|
||||
assertThat(constraintDescriptionForField("size")).isEqualTo("Size must be between 2 and 10 inclusive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageCreditCardNumber() {
|
||||
void defaultMessageCreditCardNumber() {
|
||||
assertThat(constraintDescriptionForField("creditCardNumber"))
|
||||
.isEqualTo("Must be a well-formed credit card number");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageEan() {
|
||||
void defaultMessageEan() {
|
||||
assertThat(constraintDescriptionForField("ean")).isEqualTo("Must be a well-formed EAN13 number");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageEmail() {
|
||||
void defaultMessageEmail() {
|
||||
assertThat(constraintDescriptionForField("email")).isEqualTo("Must be a well-formed email address");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageLength() {
|
||||
void defaultMessageLength() {
|
||||
assertThat(constraintDescriptionForField("length")).isEqualTo("Length must be between 2 and 10 inclusive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageLuhnCheck() {
|
||||
void defaultMessageLuhnCheck() {
|
||||
assertThat(constraintDescriptionForField("luhnCheck"))
|
||||
.isEqualTo("Must pass the Luhn Modulo 10 checksum algorithm");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageMod10Check() {
|
||||
void defaultMessageMod10Check() {
|
||||
assertThat(constraintDescriptionForField("mod10Check")).isEqualTo("Must pass the Mod10 checksum algorithm");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageMod11Check() {
|
||||
void defaultMessageMod11Check() {
|
||||
assertThat(constraintDescriptionForField("mod11Check")).isEqualTo("Must pass the Mod11 checksum algorithm");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNegative() {
|
||||
void defaultMessageNegative() {
|
||||
assertThat(constraintDescriptionForField("negative")).isEqualTo("Must be negative");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNegativeOrZero() {
|
||||
void defaultMessageNegativeOrZero() {
|
||||
assertThat(constraintDescriptionForField("negativeOrZero")).isEqualTo("Must be negative or zero");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNotBlank() {
|
||||
void defaultMessageNotBlank() {
|
||||
assertThat(constraintDescriptionForField("notBlank")).isEqualTo("Must not be blank");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNotEmpty() {
|
||||
void defaultMessageNotEmpty() {
|
||||
assertThat(constraintDescriptionForField("notEmpty")).isEqualTo("Must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageNotEmptyHibernateValidator() {
|
||||
void defaultMessageNotEmptyHibernateValidator() {
|
||||
assertThat(constraintDescriptionForField("notEmpty")).isEqualTo("Must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessagePositive() {
|
||||
void defaultMessagePositive() {
|
||||
assertThat(constraintDescriptionForField("positive")).isEqualTo("Must be positive");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessagePositiveOrZero() {
|
||||
void defaultMessagePositiveOrZero() {
|
||||
assertThat(constraintDescriptionForField("positiveOrZero")).isEqualTo("Must be positive or zero");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageRange() {
|
||||
void defaultMessageRange() {
|
||||
assertThat(constraintDescriptionForField("range")).isEqualTo("Must be at least 10 and at most 100");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultMessageUrl() {
|
||||
void defaultMessageUrl() {
|
||||
assertThat(constraintDescriptionForField("url")).isEqualTo("Must be a well-formed URL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customMessage() {
|
||||
void customMessage() {
|
||||
Thread.currentThread().setContextClassLoader(new ClassLoader() {
|
||||
|
||||
@Override
|
||||
@@ -279,7 +279,7 @@ public class ResourceBundleConstraintDescriptionResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customResourceBundle() {
|
||||
void customResourceBundle() {
|
||||
ResourceBundle bundle = new ListResourceBundle() {
|
||||
|
||||
@Override
|
||||
@@ -294,7 +294,7 @@ public class ResourceBundleConstraintDescriptionResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allBeanValidationConstraintsAreTested() throws Exception {
|
||||
void allBeanValidationConstraintsAreTested() throws Exception {
|
||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
||||
Resource[] resources = resolver.getResources("jakarta/validation/constraints/*.class");
|
||||
Set<Class<?>> beanValidationConstraints = new HashSet<>();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ import org.assertj.core.api.Condition;
|
||||
import org.assertj.core.description.TextDescription;
|
||||
import org.hibernate.validator.constraints.CompositionType;
|
||||
import org.hibernate.validator.constraints.ConstraintComposition;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -44,19 +44,19 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ValidatorConstraintResolverTests {
|
||||
class ValidatorConstraintResolverTests {
|
||||
|
||||
private final ValidatorConstraintResolver resolver = new ValidatorConstraintResolver();
|
||||
|
||||
@Test
|
||||
public void singleFieldConstraint() {
|
||||
void singleFieldConstraint() {
|
||||
List<Constraint> constraints = this.resolver.resolveForProperty("single", ConstrainedFields.class);
|
||||
assertThat(constraints).hasSize(1);
|
||||
assertThat(constraints.get(0).getName()).isEqualTo(NotNull.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldConstraints() {
|
||||
void multipleFieldConstraints() {
|
||||
List<Constraint> constraints = this.resolver.resolveForProperty("multiple", ConstrainedFields.class);
|
||||
assertThat(constraints).hasSize(2);
|
||||
assertThat(constraints.get(0)).is(constraint(NotNull.class));
|
||||
@@ -64,13 +64,13 @@ public class ValidatorConstraintResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noFieldConstraints() {
|
||||
void noFieldConstraints() {
|
||||
List<Constraint> constraints = this.resolver.resolveForProperty("none", ConstrainedFields.class);
|
||||
assertThat(constraints).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compositeConstraint() {
|
||||
void compositeConstraint() {
|
||||
List<Constraint> constraints = this.resolver.resolveForProperty("composite", ConstrainedFields.class);
|
||||
assertThat(constraints).hasSize(1);
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.cookies;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestCookiesSnippet} due to missing or
|
||||
* undocumented cookies.
|
||||
*
|
||||
* @author Clyde Stubbs
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestCookiesSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void missingRequestCookie() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestCookiesSnippet(
|
||||
Collections.singletonList(CookieDocumentation.cookieWithName("JSESSIONID").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Cookies with the following names were not found in the request: [JSESSIONID]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestCookie() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestCookiesSnippet(Collections.emptyList()).document(
|
||||
this.operationBuilder.request("http://localhost").cookie("JSESSIONID", "1234abcd5678efgh").build()))
|
||||
.withMessageEndingWith("Cookies with the following names were not documented: [JSESSIONID]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,18 +20,15 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -42,138 +39,141 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Clyde Stubbs
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestCookiesSnippetTests extends AbstractSnippetTests {
|
||||
class RequestCookiesSnippetTests {
|
||||
|
||||
public RequestCookiesSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithCookies() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithCookies(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").description("one"), cookieWithName("logged_in").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
assertThat(snippets.requestCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredRequestCookie() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredRequestCookie(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").ignored(), cookieWithName("logged_in").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`logged_in`", "two"));
|
||||
assertThat(snippets.requestCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`logged_in`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedCookiesCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedCookiesCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").description("one"), cookieWithName("logged_in").description("two")),
|
||||
true)
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.cookie("user_session", "abcd1234efgh5678")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
assertThat(snippets.requestCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalCookie() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalCookie(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestCookiesSnippet(Arrays.asList(cookieWithName("tz").description("one").optional(),
|
||||
cookieWithName("logged_in").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost").cookie("logged_in", "true").build());
|
||||
assertThat(this.generatedSnippets.requestCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").cookie("logged_in", "true").build());
|
||||
assertThat(snippets.requestCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`tz`", "one").row("`logged_in`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestCookiesWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-cookies"))
|
||||
.willReturn(snippetResource("request-cookies-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-cookies", template = "request-cookies-with-title")
|
||||
void requestCookiesWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestCookiesSnippet(Collections.singletonList(cookieWithName("tz").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies()).contains("Custom title");
|
||||
.document(operationBuilder.request("http://localhost").cookie("tz", "Europe%2FLondon").build());
|
||||
assertThat(snippets.requestCookies()).contains("Custom title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestCookiesWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-cookies"))
|
||||
.willReturn(snippetResource("request-cookies-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-cookies", template = "request-cookies-with-extra-column")
|
||||
void requestCookiesWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").description("one").attributes(key("foo").value("alpha")),
|
||||
cookieWithName("logged_in").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies()).is(//
|
||||
tableWithHeader("Name", "Description", "Foo").row("tz", "one", "alpha")
|
||||
.row("logged_in", "two", "bravo"));
|
||||
assertThat(snippets.requestCookies()).isTable((table) -> table.withHeader("Name", "Description", "Foo")
|
||||
.row("tz", "one", "alpha")
|
||||
.row("logged_in", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").description("one"), cookieWithName("logged_in").description("two")))
|
||||
.and(cookieWithName("user_session").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.cookie("user_session", "abcd1234efgh5678")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies()).is(tableWithHeader("Name", "Description").row("`tz`", "one")
|
||||
assertThat(snippets.requestCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`tz`", "one")
|
||||
.row("`logged_in`", "two")
|
||||
.row("`user_session`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptorsWithRelaxedRequestCookies() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptorsWithRelaxedRequestCookies(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestCookiesSnippet(
|
||||
Arrays.asList(cookieWithName("tz").description("one"), cookieWithName("logged_in").description("two")),
|
||||
true)
|
||||
.and(cookieWithName("user_session").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.cookie("tz", "Europe%2FLondon")
|
||||
.cookie("logged_in", "true")
|
||||
.cookie("user_session", "abcd1234efgh5678")
|
||||
.cookie("color_theme", "light")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestCookies()).is(tableWithHeader("Name", "Description").row("`tz`", "one")
|
||||
assertThat(snippets.requestCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`tz`", "one")
|
||||
.row("`logged_in`", "two")
|
||||
.row("`user_session`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableCellContentIsEscapedWhenNecessary() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void tableCellContentIsEscapedWhenNecessary(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestCookiesSnippet(Collections.singletonList(cookieWithName("Foo|Bar").description("one|two")))
|
||||
.document(this.operationBuilder.request("http://localhost").cookie("Foo|Bar", "baz").build());
|
||||
assertThat(this.generatedSnippets.requestCookies()).is(tableWithHeader("Name", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.request("http://localhost").cookie("Foo|Bar", "baz").build());
|
||||
assertThat(snippets.requestCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void missingRequestCookie(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestCookiesSnippet(
|
||||
Collections.singletonList(CookieDocumentation.cookieWithName("JSESSIONID").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Cookies with the following names were not found in the request: [JSESSIONID]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedRequestCookie(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestCookiesSnippet(Collections.emptyList()).document(
|
||||
operationBuilder.request("http://localhost").cookie("JSESSIONID", "1234abcd5678efgh").build()))
|
||||
.withMessageEndingWith("Cookies with the following names were not documented: [JSESSIONID]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.cookies;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link ResponseCookiesSnippet} due to missing or
|
||||
* undocumented cookies.
|
||||
*
|
||||
* @author Clyde Stubbs
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseCookiesSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void missingResponseCookie() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseCookiesSnippet(
|
||||
Collections.singletonList(cookieWithName("JSESSIONID").description("one")))
|
||||
.document(this.operationBuilder.response().build()))
|
||||
.withMessage("Cookies with the following names were not found in the response: [JSESSIONID]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseCookie() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseCookiesSnippet(Collections.emptyList())
|
||||
.document(this.operationBuilder.response().cookie("JSESSIONID", "1234abcd5678efgh").build()))
|
||||
.withMessageEndingWith("Cookies with the following names were not documented: [JSESSIONID]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,18 +20,12 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -42,141 +36,127 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Clyde Stubbs
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseCookiesSnippetTests extends AbstractSnippetTests {
|
||||
class ResponseCookiesSnippetTests {
|
||||
|
||||
public ResponseCookiesSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCookies() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithCookies(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseCookiesSnippet(Arrays.asList(cookieWithName("has_recent_activity").description("one"),
|
||||
cookieWithName("user_session").description("two")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredResponseCookie() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredResponseCookie(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseCookiesSnippet(Arrays.asList(cookieWithName("has_recent_activity").ignored(),
|
||||
cookieWithName("user_session").description("two")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`user_session`", "two"));
|
||||
assertThat(snippets.responseCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`user_session`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedResponseCookiesCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedResponseCookiesCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseCookiesSnippet(Arrays.asList(cookieWithName("has_recent_activity").description("one"),
|
||||
cookieWithName("user_session").description("two")), true)
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.cookie("some_cookie", "value")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalResponseCookie() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalResponseCookie(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseCookiesSnippet(Arrays.asList(cookieWithName("has_recent_activity").description("one").optional(),
|
||||
cookieWithName("user_session").description("two")))
|
||||
.document(this.operationBuilder.response().cookie("user_session", "1234abcd5678efgh").build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
.document(operationBuilder.response().cookie("user_session", "1234abcd5678efgh").build());
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseCookiesWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-cookies"))
|
||||
.willReturn(snippetResource("response-cookies-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-cookies", template = "response-cookies-with-title")
|
||||
void responseCookiesWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseCookiesSnippet(Collections.singletonList(cookieWithName("has_recent_activity").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies()).contains("Custom title");
|
||||
.document(operationBuilder.response().cookie("has_recent_activity", "true").build());
|
||||
assertThat(snippets.responseCookies()).contains("Custom title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseCookiesWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-cookies"))
|
||||
.willReturn(snippetResource("response-cookies-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-cookies", template = "response-cookies-with-extra-column")
|
||||
void responseCookiesWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseCookiesSnippet(Arrays.asList(
|
||||
cookieWithName("has_recent_activity").description("one").attributes(key("foo").value("alpha")),
|
||||
cookieWithName("user_session").description("two").attributes(key("foo").value("bravo")),
|
||||
cookieWithName("color_theme").description("three").attributes(key("foo").value("charlie"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.cookie("color_theme", "high_contrast")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description", "Foo").row("has_recent_activity", "one", "alpha")
|
||||
.row("user_session", "two", "bravo")
|
||||
.row("color_theme", "three", "charlie"));
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description", "Foo")
|
||||
.row("has_recent_activity", "one", "alpha")
|
||||
.row("user_session", "two", "bravo")
|
||||
.row("color_theme", "three", "charlie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
CookieDocumentation
|
||||
.responseCookies(cookieWithName("has_recent_activity").description("one"),
|
||||
cookieWithName("user_session").description("two"))
|
||||
.and(cookieWithName("color_theme").description("three"))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.cookie("color_theme", "light")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two")
|
||||
.row("`color_theme`", "three"));
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`has_recent_activity`", "one")
|
||||
.row("`user_session`", "two")
|
||||
.row("`color_theme`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptorsWithRelaxedResponseCookies() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptorsWithRelaxedResponseCookies(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
CookieDocumentation.relaxedResponseCookies(cookieWithName("has_recent_activity").description("one"))
|
||||
.and(cookieWithName("color_theme").description("two"))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.cookie("has_recent_activity", "true")
|
||||
.cookie("user_session", "1234abcd5678efgh")
|
||||
.cookie("color_theme", "light")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseCookies())
|
||||
.is(tableWithHeader("Name", "Description").row("`has_recent_activity`", "one").row("`color_theme`", "two"));
|
||||
assertThat(snippets.responseCookies()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`has_recent_activity`", "one")
|
||||
.row("`color_theme`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableCellContentIsEscapedWhenNecessary() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void tableCellContentIsEscapedWhenNecessary(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseCookiesSnippet(Collections.singletonList(cookieWithName("Foo|Bar").description("one|two")))
|
||||
.document(this.operationBuilder.response().cookie("Foo|Bar", "baz").build());
|
||||
assertThat(this.generatedSnippets.responseCookies()).is(tableWithHeader("Name", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
.document(operationBuilder.response().cookie("Foo|Bar", "baz").build());
|
||||
assertThat(snippets.responseCookies())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.headers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestHeadersSnippet} due to missing or
|
||||
* undocumented headers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestHeadersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void missingRequestHeader() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Headers with the following names were not found in the request: [Accept]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestHeaderAndMissingRequestHeader() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").header("X-Test", "test").build()))
|
||||
.withMessageEndingWith("Headers with the following names were not found in the request: [Accept]");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,18 +19,15 @@ package org.springframework.restdocs.headers;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -41,19 +38,15 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andreas Evers
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestHeadersSnippetTests extends AbstractSnippetTests {
|
||||
class RequestHeadersSnippetTests {
|
||||
|
||||
public RequestHeadersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one"),
|
||||
headerWithName("Accept").description("two"), headerWithName("Accept-Encoding").description("three"),
|
||||
headerWithName("Accept-Language").description("four"),
|
||||
headerWithName("Cache-Control").description("five"), headerWithName("Connection").description("six")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.header("X-Test", "test")
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Encoding", "gzip, deflate")
|
||||
@@ -61,79 +54,69 @@ public class RequestHeadersSnippetTests extends AbstractSnippetTests {
|
||||
.header("Cache-Control", "max-age=0")
|
||||
.header("Connection", "keep-alive")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one")
|
||||
.row("`Accept`", "two")
|
||||
.row("`Accept-Encoding`", "three")
|
||||
.row("`Accept-Language`", "four")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Connection`", "six"));
|
||||
assertThat(snippets.requestHeaders()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`X-Test`", "one")
|
||||
.row("`Accept`", "two")
|
||||
.row("`Accept-Encoding`", "three")
|
||||
.row("`Accept-Language`", "four")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Connection`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void caseInsensitiveRequestHeaders() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void caseInsensitiveRequestHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")))
|
||||
.document(this.operationBuilder.request("/").header("X-test", "test").build());
|
||||
assertThat(this.generatedSnippets.requestHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
.document(operationBuilder.request("/").header("X-test", "test").build());
|
||||
assertThat(snippets.requestHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestHeader() throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.header("X-Test", "test")
|
||||
.header("Accept", "*/*")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
@RenderedSnippetTest
|
||||
void undocumentedRequestHeader(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one"))).document(
|
||||
operationBuilder.request("http://localhost").header("X-Test", "test").header("Accept", "*/*").build());
|
||||
assertThat(snippets.requestHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHeadersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-headers"))
|
||||
.willReturn(snippetResource("request-headers-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-headers", template = "request-headers-with-title")
|
||||
void requestHeadersWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.header("X-Test", "test")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestHeaders()).contains("Custom title");
|
||||
.document(operationBuilder.request("http://localhost").header("X-Test", "test").build());
|
||||
assertThat(snippets.requestHeaders()).contains("Custom title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestHeadersWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-headers"))
|
||||
.willReturn(snippetResource("request-headers-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-headers", template = "request-headers-with-extra-column")
|
||||
void requestHeadersWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestHeadersSnippet(
|
||||
Arrays.asList(headerWithName("X-Test").description("one").attributes(key("foo").value("alpha")),
|
||||
headerWithName("Accept-Encoding").description("two").attributes(key("foo").value("bravo")),
|
||||
headerWithName("Accept").description("three").attributes(key("foo").value("charlie"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.header("X-Test", "test")
|
||||
.header("Accept-Encoding", "gzip, deflate")
|
||||
.header("Accept", "*/*")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestHeaders()).is(//
|
||||
tableWithHeader("Name", "Description", "Foo").row("X-Test", "one", "alpha")
|
||||
.row("Accept-Encoding", "two", "bravo")
|
||||
.row("Accept", "three", "charlie"));
|
||||
assertThat(snippets.requestHeaders()).isTable((table) -> table.withHeader("Name", "Description", "Foo")
|
||||
.row("X-Test", "one", "alpha")
|
||||
.row("Accept-Encoding", "two", "bravo")
|
||||
.row("Accept", "three", "charlie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
HeaderDocumentation
|
||||
.requestHeaders(headerWithName("X-Test").description("one"), headerWithName("Accept").description("two"),
|
||||
headerWithName("Accept-Encoding").description("three"),
|
||||
headerWithName("Accept-Language").description("four"))
|
||||
.and(headerWithName("Cache-Control").description("five"), headerWithName("Connection").description("six"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.header("X-Test", "test")
|
||||
.header("Accept", "*/*")
|
||||
.header("Accept-Encoding", "gzip, deflate")
|
||||
@@ -141,28 +124,39 @@ public class RequestHeadersSnippetTests extends AbstractSnippetTests {
|
||||
.header("Cache-Control", "max-age=0")
|
||||
.header("Connection", "keep-alive")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one")
|
||||
.row("`Accept`", "two")
|
||||
.row("`Accept-Encoding`", "three")
|
||||
.row("`Accept-Language`", "four")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Connection`", "six"));
|
||||
assertThat(snippets.requestHeaders()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`X-Test`", "one")
|
||||
.row("`Accept`", "two")
|
||||
.row("`Accept-Encoding`", "three")
|
||||
.row("`Accept-Language`", "four")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Connection`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableCellContentIsEscapedWhenNecessary() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void tableCellContentIsEscapedWhenNecessary(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestHeadersSnippet(Arrays.asList(headerWithName("Foo|Bar").description("one|two")))
|
||||
.document(this.operationBuilder.request("http://localhost").header("Foo|Bar", "baz").build());
|
||||
assertThat(this.generatedSnippets.requestHeaders()).is(tableWithHeader("Name", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.request("http://localhost").header("Foo|Bar", "baz").build());
|
||||
assertThat(snippets.requestHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void missingRequestHeader(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Headers with the following names were not found in the request: [Accept]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedRequestHeaderAndMissingRequestHeader(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestHeadersSnippet(Arrays.asList(headerWithName("Accept").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").header("X-Test", "test").build()))
|
||||
.withMessageEndingWith("Headers with the following names were not found in the request: [Accept]");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.headers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link ResponseHeadersSnippet} due to missing or
|
||||
* undocumented headers.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseHeadersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void missingResponseHeader() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type").description("one")))
|
||||
.document(this.operationBuilder.response().build()))
|
||||
.withMessage("Headers with the following names were not found" + " in the response: [Content-Type]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeaderAndMissingResponseHeader() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type").description("one")))
|
||||
.document(this.operationBuilder.response().header("X-Test", "test").build()))
|
||||
.withMessageEndingWith("Headers with the following names were not found in the response: [Content-Type]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,18 +19,15 @@ package org.springframework.restdocs.headers;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -41,119 +38,120 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andreas Evers
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseHeadersSnippetTests extends AbstractSnippetTests {
|
||||
class ResponseHeadersSnippetTests {
|
||||
|
||||
public ResponseHeadersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithHeaders() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one"),
|
||||
headerWithName("Content-Type").description("two"), headerWithName("Etag").description("three"),
|
||||
headerWithName("Cache-Control").description("five"), headerWithName("Vary").description("six")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.header("X-Test", "test")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Etag", "lskjadldj3ii32l2ij23")
|
||||
.header("Cache-Control", "max-age=0")
|
||||
.header("Vary", "User-Agent")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one")
|
||||
.row("`Content-Type`", "two")
|
||||
.row("`Etag`", "three")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Vary`", "six"));
|
||||
assertThat(snippets.responseHeaders()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`X-Test`", "one")
|
||||
.row("`Content-Type`", "two")
|
||||
.row("`Etag`", "three")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Vary`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void caseInsensitiveResponseHeaders() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void caseInsensitiveResponseHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")))
|
||||
.document(this.operationBuilder.response().header("X-test", "test").build());
|
||||
assertThat(this.generatedSnippets.responseHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
.document(operationBuilder.response().header("X-test", "test").build());
|
||||
assertThat(snippets.responseHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedResponseHeader() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void undocumentedResponseHeader(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")))
|
||||
.document(this.operationBuilder.response().header("X-Test", "test").header("Content-Type", "*/*").build());
|
||||
assertThat(this.generatedSnippets.responseHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
.document(operationBuilder.response().header("X-Test", "test").header("Content-Type", "*/*").build());
|
||||
assertThat(snippets.responseHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`X-Test`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseHeadersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-headers"))
|
||||
.willReturn(snippetResource("response-headers-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-headers", template = "response-headers-with-title")
|
||||
void responseHeadersWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("X-Test").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.header("X-Test", "test")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseHeaders()).contains("Custom title");
|
||||
.document(operationBuilder.response().header("X-Test", "test").build());
|
||||
assertThat(snippets.responseHeaders()).contains("Custom title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseHeadersWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-headers"))
|
||||
.willReturn(snippetResource("response-headers-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-headers", template = "response-headers-with-extra-column")
|
||||
void responseHeadersWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseHeadersSnippet(
|
||||
Arrays.asList(headerWithName("X-Test").description("one").attributes(key("foo").value("alpha")),
|
||||
headerWithName("Content-Type").description("two").attributes(key("foo").value("bravo")),
|
||||
headerWithName("Etag").description("three").attributes(key("foo").value("charlie"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.document(operationBuilder.response()
|
||||
.header("X-Test", "test")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Etag", "lskjadldj3ii32l2ij23")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseHeaders())
|
||||
.is(tableWithHeader("Name", "Description", "Foo").row("X-Test", "one", "alpha")
|
||||
.row("Content-Type", "two", "bravo")
|
||||
.row("Etag", "three", "charlie"));
|
||||
assertThat(snippets.responseHeaders()).isTable((table) -> table.withHeader("Name", "Description", "Foo")
|
||||
.row("X-Test", "one", "alpha")
|
||||
.row("Content-Type", "two", "bravo")
|
||||
.row("Etag", "three", "charlie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
HeaderDocumentation
|
||||
.responseHeaders(headerWithName("X-Test").description("one"),
|
||||
headerWithName("Content-Type").description("two"), headerWithName("Etag").description("three"))
|
||||
.and(headerWithName("Cache-Control").description("five"), headerWithName("Vary").description("six"))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.header("X-Test", "test")
|
||||
.header("Content-Type", "application/json")
|
||||
.header("Etag", "lskjadldj3ii32l2ij23")
|
||||
.header("Cache-Control", "max-age=0")
|
||||
.header("Vary", "User-Agent")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseHeaders())
|
||||
.is(tableWithHeader("Name", "Description").row("`X-Test`", "one")
|
||||
.row("`Content-Type`", "two")
|
||||
.row("`Etag`", "three")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Vary`", "six"));
|
||||
assertThat(snippets.responseHeaders()).isTable((table) -> table.withHeader("Name", "Description")
|
||||
.row("`X-Test`", "one")
|
||||
.row("`Content-Type`", "two")
|
||||
.row("`Etag`", "three")
|
||||
.row("`Cache-Control`", "five")
|
||||
.row("`Vary`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableCellContentIsEscapedWhenNecessary() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void tableCellContentIsEscapedWhenNecessary(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseHeadersSnippet(Arrays.asList(headerWithName("Foo|Bar").description("one|two")))
|
||||
.document(this.operationBuilder.response().header("Foo|Bar", "baz").build());
|
||||
assertThat(this.generatedSnippets.responseHeaders()).is(tableWithHeader("Name", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.response().header("Foo|Bar", "baz").build());
|
||||
assertThat(snippets.responseHeaders())
|
||||
.isTable((table) -> table.withHeader("Name", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void missingResponseHeader(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type").description("one")))
|
||||
.document(operationBuilder.response().build()))
|
||||
.withMessage("Headers with the following names were not found" + " in the response: [Content-Type]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedResponseHeaderAndMissingResponseHeader(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseHeadersSnippet(Arrays.asList(headerWithName("Content-Type").description("one")))
|
||||
.document(operationBuilder.response().header("X-Test", "test").build()))
|
||||
.withMessageEndingWith("Headers with the following names were not found in the response: [Content-Type]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,20 +18,14 @@ package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
|
||||
@@ -41,162 +35,160 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andy Wilkinson
|
||||
* @author Jonathan Pearlin
|
||||
*/
|
||||
public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
||||
class HttpRequestSnippetTests {
|
||||
|
||||
private static final String BOUNDARY = "6o2knFse3p53ty9dmcQvWAIx1zInP11uCfbm";
|
||||
|
||||
public HttpRequestSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost/foo").header("Alpha", "a").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo").header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
|
||||
.document(operationBuilder.request("http://localhost/foo").header("Alpha", "a").build());
|
||||
assertThat(snippets.httpRequest())
|
||||
.isHttpRequest((request) -> request.get("/foo").header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost/foo?b=bravo").header("Alpha", "a").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo?b=bravo").header("Alpha", "a")
|
||||
.header(HttpHeaders.HOST, "localhost"));
|
||||
.document(operationBuilder.request("http://localhost/foo?b=bravo").header("Alpha", "a").build());
|
||||
assertThat(snippets.httpRequest()).isHttpRequest(
|
||||
(request) -> request.get("/foo?b=bravo").header("Alpha", "a").header(HttpHeaders.HOST, "localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithPort() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithPort(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost:8080/foo").header("Alpha", "a").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo").header("Alpha", "a").header(HttpHeaders.HOST, "localhost:8080"));
|
||||
.document(operationBuilder.request("http://localhost:8080/foo").header("Alpha", "a").build());
|
||||
assertThat(snippets.httpRequest()).isHttpRequest(
|
||||
(request) -> request.get("/foo").header("Alpha", "a").header(HttpHeaders.HOST, "localhost:8080"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithCookies() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo")
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithCookies(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/foo")
|
||||
.cookie("name1", "value1")
|
||||
.cookie("name2", "value2")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo").header(HttpHeaders.HOST, "localhost")
|
||||
.header(HttpHeaders.COOKIE, "name1=value1; name2=value2"));
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.get("/foo")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.header(HttpHeaders.COOKIE, "name1=value1; name2=value2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryString() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?bar=baz").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo?bar=baz").header(HttpHeaders.HOST, "localhost"));
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/foo?bar=baz").build());
|
||||
assertThat(snippets.httpRequest())
|
||||
.isHttpRequest((request) -> request.get("/foo?bar=baz").header(HttpHeaders.HOST, "localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryStringWithNoValue() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo?bar").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo?bar").header(HttpHeaders.HOST, "localhost"));
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithQueryStringWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/foo?bar").build());
|
||||
assertThat(snippets.httpRequest())
|
||||
.isHttpRequest((request) -> request.get("/foo?bar").header(HttpHeaders.HOST, "localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithContent(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
String content = "Hello, world";
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("POST").content(content).build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.POST, "/foo").header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("POST").content(content).build());
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/foo")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithContentAndQueryParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithContentAndQueryParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
String content = "Hello, world";
|
||||
new HttpRequestSnippet().document(
|
||||
this.operationBuilder.request("http://localhost/foo?a=alpha").method("POST").content(content).build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.POST, "/foo?a=alpha").header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
new HttpRequestSnippet()
|
||||
.document(operationBuilder.request("http://localhost/foo?a=alpha").method("POST").content(content).build());
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/foo?a=alpha")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithCharset() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void postRequestWithCharset(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
||||
byte[] contentBytes = japaneseContent.getBytes("UTF-8");
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo")
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/foo")
|
||||
.method("POST")
|
||||
.header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.content(contentBytes)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.POST, "/foo").header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length)
|
||||
.content(japaneseContent));
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/foo")
|
||||
.header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length)
|
||||
.content(japaneseContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putRequestWithContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void putRequestWithContent(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
String content = "Hello, world";
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost/foo").method("PUT").content(content).build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.PUT, "/foo").header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
.document(operationBuilder.request("http://localhost/foo").method("PUT").content(content).build());
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.put("/foo")
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPost() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPost(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
.build());
|
||||
String expectedContent = createPart(
|
||||
String.format("Content-Disposition: " + "form-data; " + "name=image%n%n<< data >>"));
|
||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/upload")
|
||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPut() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPut(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/upload")
|
||||
.method("PUT")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
.build());
|
||||
String expectedContent = createPart(
|
||||
String.format("Content-Disposition: " + "form-data; " + "name=image%n%n<< data >>"));
|
||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.PUT, "/upload")
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.put("/upload")
|
||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPatch() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPatch(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/upload")
|
||||
.method("PATCH")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
.build());
|
||||
String expectedContent = createPart(
|
||||
String.format("Content-Disposition: " + "form-data; " + "name=image%n%n<< data >>"));
|
||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.PATCH, "/upload")
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.patch("/upload")
|
||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithFilename() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithFilename(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
@@ -204,15 +196,16 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
||||
.build());
|
||||
String expectedContent = createPart(String
|
||||
.format("Content-Disposition: " + "form-data; " + "name=image; filename=image.png%n%n<< data >>"));
|
||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/upload")
|
||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartPostWithContentType() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/upload")
|
||||
@RenderedSnippetTest
|
||||
void multipartPostWithContentType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpRequestSnippet().document(operationBuilder.request("http://localhost/upload")
|
||||
.method("POST")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
.part("image", "<< data >>".getBytes())
|
||||
@@ -220,38 +213,35 @@ public class HttpRequestSnippetTests extends AbstractSnippetTests {
|
||||
.build());
|
||||
String expectedContent = createPart(String
|
||||
.format("Content-Disposition: form-data; name=image%nContent-Type: " + "image/png%n%n<< data >>"));
|
||||
assertThat(this.generatedSnippets.httpRequest()).is(httpRequest(RequestMethod.POST, "/upload")
|
||||
assertThat(snippets.httpRequest()).isHttpRequest((request) -> request.post("/upload")
|
||||
.header("Content-Type", "multipart/form-data; boundary=" + BOUNDARY)
|
||||
.header(HttpHeaders.HOST, "localhost")
|
||||
.content(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithCustomHost() throws IOException {
|
||||
new HttpRequestSnippet().document(this.operationBuilder.request("http://localhost/foo")
|
||||
.header(HttpHeaders.HOST, "api.example.com")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.GET, "/foo").header(HttpHeaders.HOST, "api.example.com"));
|
||||
@RenderedSnippetTest
|
||||
void getRequestWithCustomHost(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet().document(
|
||||
operationBuilder.request("http://localhost/foo").header(HttpHeaders.HOST, "api.example.com").build());
|
||||
assertThat(snippets.httpRequest())
|
||||
.isHttpRequest((request) -> request.get("/foo").header(HttpHeaders.HOST, "api.example.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithCustomSnippetAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("http-request")).willReturn(snippetResource("http-request-with-title"));
|
||||
new HttpRequestSnippet(attributes(key("title").value("Title for the request"))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost/foo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpRequest()).contains("Title for the request");
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "http-request", template = "http-request-with-title")
|
||||
void requestWithCustomSnippetAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpRequestSnippet(attributes(key("title").value("Title for the request")))
|
||||
.document(operationBuilder.request("http://localhost/foo").build());
|
||||
assertThat(snippets.httpRequest()).contains("Title for the request");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void deleteWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpRequestSnippet()
|
||||
.document(this.operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(this.generatedSnippets.httpRequest())
|
||||
.is(httpRequest(RequestMethod.DELETE, "/foo?a=alpha&b=bravo").header("Host", "localhost"));
|
||||
.document(operationBuilder.request("http://localhost/foo?a=alpha&b=bravo").method("DELETE").build());
|
||||
assertThat(snippets.httpRequest())
|
||||
.isHttpRequest((request) -> request.delete("/foo?a=alpha&b=bravo").header("Host", "localhost"));
|
||||
}
|
||||
|
||||
private String createPart(String content) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,21 +18,16 @@ package org.springframework.restdocs.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
|
||||
@@ -42,72 +37,66 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andy Wilkinson
|
||||
* @author Jonathan Pearlin
|
||||
*/
|
||||
public class HttpResponseSnippetTests extends AbstractSnippetTests {
|
||||
class HttpResponseSnippetTests {
|
||||
|
||||
public HttpResponseSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
@RenderedSnippetTest
|
||||
void basicResponse(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpResponseSnippet().document(operationBuilder.build());
|
||||
assertThat(snippets.httpResponse()).isHttpResponse((response) -> response.ok());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicResponse() throws IOException {
|
||||
new HttpResponseSnippet().document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.httpResponse()).is(httpResponse(HttpStatus.OK));
|
||||
@RenderedSnippetTest
|
||||
void nonOkResponse(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpResponseSnippet().document(operationBuilder.response().status(HttpStatus.BAD_REQUEST).build());
|
||||
assertThat(snippets.httpResponse()).isHttpResponse((response) -> response.badRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOkResponse() throws IOException {
|
||||
new HttpResponseSnippet().document(this.operationBuilder.response().status(HttpStatus.BAD_REQUEST).build());
|
||||
assertThat(this.generatedSnippets.httpResponse()).is(httpResponse(HttpStatus.BAD_REQUEST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithHeaders() throws IOException {
|
||||
new HttpResponseSnippet().document(this.operationBuilder.response()
|
||||
@RenderedSnippetTest
|
||||
void responseWithHeaders(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpResponseSnippet().document(operationBuilder.response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.header("a", "alpha")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpResponse())
|
||||
.is(httpResponse(HttpStatus.OK).header("Content-Type", "application/json").header("a", "alpha"));
|
||||
assertThat(snippets.httpResponse()).isHttpResponse(
|
||||
(response) -> response.ok().header("Content-Type", "application/json").header("a", "alpha"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithContent(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
String content = "content";
|
||||
new HttpResponseSnippet().document(this.operationBuilder.response().content(content).build());
|
||||
assertThat(this.generatedSnippets.httpResponse()).is(httpResponse(HttpStatus.OK).content(content)
|
||||
new HttpResponseSnippet().document(operationBuilder.response().content(content).build());
|
||||
assertThat(snippets.httpResponse()).isHttpResponse((response) -> response.ok()
|
||||
.content(content)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, content.getBytes().length));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCharset() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithCharset(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
||||
byte[] contentBytes = japaneseContent.getBytes("UTF-8");
|
||||
new HttpResponseSnippet().document(this.operationBuilder.response()
|
||||
new HttpResponseSnippet().document(operationBuilder.response()
|
||||
.header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.content(contentBytes)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpResponse())
|
||||
.is(httpResponse(HttpStatus.OK).header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.content(japaneseContent)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length));
|
||||
assertThat(snippets.httpResponse()).isHttpResponse((response) -> response.ok()
|
||||
.header("Content-Type", "text/plain;charset=UTF-8")
|
||||
.content(japaneseContent)
|
||||
.header(HttpHeaders.CONTENT_LENGTH, contentBytes.length));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCustomSnippetAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("http-response"))
|
||||
.willReturn(snippetResource("http-response-with-title"));
|
||||
new HttpResponseSnippet(attributes(key("title").value("Title for the response"))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.httpResponse()).contains("Title for the response");
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "http-response", template = "http-response-with-title")
|
||||
void responseWithCustomSnippetAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new HttpResponseSnippet(attributes(key("title").value("Title for the response")))
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.httpResponse()).contains("Title for the response");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCustomStatus() throws IOException {
|
||||
new HttpResponseSnippet()
|
||||
.document(this.operationBuilder.response().status(HttpStatusCode.valueOf(215)).build());
|
||||
assertThat(this.generatedSnippets.httpResponse()).is(httpResponse(215));
|
||||
@RenderedSnippetTest
|
||||
void responseWithCustomStatus(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new HttpResponseSnippet().document(operationBuilder.response().status(HttpStatusCode.valueOf(215)).build());
|
||||
assertThat(snippets.httpResponse()).isHttpResponse(((response) -> response.status(215)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -37,18 +37,18 @@ import static org.mockito.Mockito.verify;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ContentTypeLinkExtractorTests {
|
||||
class ContentTypeLinkExtractorTests {
|
||||
|
||||
private final OperationResponseFactory responseFactory = new OperationResponseFactory();
|
||||
|
||||
@Test
|
||||
public void extractionFailsWithNullContentType() {
|
||||
void extractionFailsWithNullContentType() {
|
||||
assertThatIllegalStateException().isThrownBy(() -> new ContentTypeLinkExtractor()
|
||||
.extractLinks(this.responseFactory.create(HttpStatus.OK, new HttpHeaders(), null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractorCalledWithMatchingContextType() throws IOException {
|
||||
void extractorCalledWithMatchingContextType() throws IOException {
|
||||
Map<MediaType, LinkExtractor> extractors = new HashMap<>();
|
||||
LinkExtractor extractor = mock(LinkExtractor.class);
|
||||
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
||||
@@ -60,7 +60,7 @@ public class ContentTypeLinkExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractorCalledWithCompatibleContextType() throws IOException {
|
||||
void extractorCalledWithCompatibleContextType() throws IOException {
|
||||
Map<MediaType, LinkExtractor> extractors = new HashMap<>();
|
||||
LinkExtractor extractor = mock(LinkExtractor.class);
|
||||
extractors.put(MediaType.APPLICATION_JSON, extractor);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,10 +24,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedClass;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
@@ -39,13 +38,13 @@ import org.springframework.util.MultiValueMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Parameterized tests for {@link HalLinkExtractor} and {@link AtomLinkExtractor} with
|
||||
* various payloads.
|
||||
* Tests for {@link HalLinkExtractor} and {@link AtomLinkExtractor} with various payloads.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class LinkExtractorsPayloadTests {
|
||||
@ParameterizedClass(name = "{1}")
|
||||
@MethodSource("parameters")
|
||||
class LinkExtractorsPayloadTests {
|
||||
|
||||
private final OperationResponseFactory responseFactory = new OperationResponseFactory();
|
||||
|
||||
@@ -53,25 +52,24 @@ public class LinkExtractorsPayloadTests {
|
||||
|
||||
private final String linkType;
|
||||
|
||||
@Parameters(name = "{1}")
|
||||
public static Collection<Object[]> data() {
|
||||
static Collection<Object[]> parameters() {
|
||||
return Arrays.asList(new Object[] { new HalLinkExtractor(), "hal" },
|
||||
new Object[] { new AtomLinkExtractor(), "atom" });
|
||||
}
|
||||
|
||||
public LinkExtractorsPayloadTests(LinkExtractor linkExtractor, String linkType) {
|
||||
LinkExtractorsPayloadTests(LinkExtractor linkExtractor, String linkType) {
|
||||
this.linkExtractor = linkExtractor;
|
||||
this.linkType = linkType;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLink() throws IOException {
|
||||
void singleLink() throws IOException {
|
||||
Map<String, List<Link>> links = this.linkExtractor.extractLinks(createResponse("single-link"));
|
||||
assertLinks(Arrays.asList(new Link("alpha", "https://alpha.example.com", "Alpha")), links);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinksWithDifferentRels() throws IOException {
|
||||
void multipleLinksWithDifferentRels() throws IOException {
|
||||
Map<String, List<Link>> links = this.linkExtractor
|
||||
.extractLinks(createResponse("multiple-links-different-rels"));
|
||||
assertLinks(Arrays.asList(new Link("alpha", "https://alpha.example.com", "Alpha"),
|
||||
@@ -79,20 +77,20 @@ public class LinkExtractorsPayloadTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLinksWithSameRels() throws IOException {
|
||||
void multipleLinksWithSameRels() throws IOException {
|
||||
Map<String, List<Link>> links = this.linkExtractor.extractLinks(createResponse("multiple-links-same-rels"));
|
||||
assertLinks(Arrays.asList(new Link("alpha", "https://alpha.example.com/one", "Alpha one"),
|
||||
new Link("alpha", "https://alpha.example.com/two")), links);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noLinks() throws IOException {
|
||||
void noLinks() throws IOException {
|
||||
Map<String, List<Link>> links = this.linkExtractor.extractLinks(createResponse("no-links"));
|
||||
assertLinks(Collections.<Link>emptyList(), links);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksInTheWrongFormat() throws IOException {
|
||||
void linksInTheWrongFormat() throws IOException {
|
||||
Map<String, List<Link>> links = this.linkExtractor.extractLinks(createResponse("wrong-format"));
|
||||
assertLinks(Collections.<Link>emptyList(), links);
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.hypermedia;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link LinksSnippet} due to missing or undocumented
|
||||
* links.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class LinksSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedLink() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Collections.<LinkDescriptor>emptyList())
|
||||
.document(this.operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not documented: [foo]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingLink() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor(),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(this.operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not found in the response: [foo]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedLinkAndMissingLink() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(this.operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not documented: [a]. Links with the following"
|
||||
+ " relations were not found in the response: [foo]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkWithNoDescription() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Arrays.asList(new LinkDescriptor("foo")))
|
||||
.document(this.operationBuilder.build()))
|
||||
.withMessage("No description was provided for the link with rel 'foo' and no title was available"
|
||||
+ " from the link in the payload");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,17 @@ package org.springframework.restdocs.hypermedia;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
|
||||
@@ -39,115 +37,145 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class LinksSnippetTests extends AbstractSnippetTests {
|
||||
class LinksSnippetTests {
|
||||
|
||||
public LinksSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredLink() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredLink(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
Arrays.asList(new LinkDescriptor("a").ignored(), new LinkDescriptor("b").description("Link b")))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links()).is(tableWithHeader("Relation", "Description").row("`b`", "Link b"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`b`", "Link b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedLinksCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedLinksCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
Arrays.asList(new LinkDescriptor("b").description("Link b")), true)
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links()).is(tableWithHeader("Relation", "Description").row("`b`", "Link b"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`b`", "Link b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalLink() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalLink(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "blah")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar").optional()))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links()).is(tableWithHeader("Relation", "Description").row("`foo`", "bar"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`foo`", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalLink() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalLink(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor(),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar").optional()))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links()).is(tableWithHeader("Relation", "Description").row("`foo`", "bar"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`foo`", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void documentedLinks() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void documentedLinks(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
Arrays.asList(new LinkDescriptor("a").description("one"), new LinkDescriptor("b").description("two")))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links())
|
||||
.is(tableWithHeader("Relation", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linkDescriptionFromTitleInPayload() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void linkDescriptionFromTitleInPayload(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new LinksSnippet(
|
||||
new StubLinkExtractor().withLinks(new Link("a", "alpha", "Link a"), new Link("b", "bravo", "Link b")),
|
||||
Arrays.asList(new LinkDescriptor("a").description("one"), new LinkDescriptor("b")))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links())
|
||||
.is(tableWithHeader("Relation", "Description").row("`a`", "one").row("`b`", "Link b"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`a`", "one").row("`b`", "Link b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("links")).willReturn(snippetResource("links-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "links", template = "links-with-title")
|
||||
void linksWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
Arrays.asList(new LinkDescriptor("a").description("one"), new LinkDescriptor("b").description("two")),
|
||||
attributes(key("title").value("Title for the links")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.links()).contains("Title for the links");
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links()).contains("Title for the links");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("links")).willReturn(snippetResource("links-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "links", template = "links-with-extra-column")
|
||||
void linksWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
Arrays.asList(new LinkDescriptor("a").description("one").attributes(key("foo").value("alpha")),
|
||||
new LinkDescriptor("b").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.links())
|
||||
.is(tableWithHeader("Relation", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links()).isTable((table) -> table.withHeader("Relation", "Description", "Foo")
|
||||
.row("a", "one", "alpha")
|
||||
.row("b", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
HypermediaDocumentation
|
||||
.links(new StubLinkExtractor().withLinks(new Link("a", "alpha"), new Link("b", "bravo")),
|
||||
new LinkDescriptor("a").description("one"))
|
||||
.and(new LinkDescriptor("b").description("two"))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links())
|
||||
.is(tableWithHeader("Relation", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tableCellContentIsEscapedWhenNecessary() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void tableCellContentIsEscapedWhenNecessary(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new LinksSnippet(new StubLinkExtractor().withLinks(new Link("Foo|Bar", "foo")),
|
||||
Arrays.asList(new LinkDescriptor("Foo|Bar").description("one|two")))
|
||||
.document(this.operationBuilder.build());
|
||||
assertThat(this.generatedSnippets.links()).is(tableWithHeader("Relation", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.build());
|
||||
assertThat(snippets.links())
|
||||
.isTable((table) -> table.withHeader("Relation", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedLink(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Collections.<LinkDescriptor>emptyList())
|
||||
.document(operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not documented: [foo]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingLink(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor(),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not found in the response: [foo]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedLinkAndMissingLink(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("a", "alpha")),
|
||||
Arrays.asList(new LinkDescriptor("foo").description("bar")))
|
||||
.document(operationBuilder.build()))
|
||||
.withMessage("Links with the following relations were not documented: [a]. Links with the following"
|
||||
+ " relations were not found in the response: [foo]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void linkWithNoDescription(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new LinksSnippet(new StubLinkExtractor().withLinks(new Link("foo", "bar")),
|
||||
Arrays.asList(new LinkDescriptor("foo")))
|
||||
.document(operationBuilder.build()))
|
||||
.withMessage("No description was provided for the link with rel 'foo' and no title was available"
|
||||
+ " from the link in the payload");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.operation.preprocess;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -39,7 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class ContentModifyingOperationPreprocessorTests {
|
||||
class ContentModifyingOperationPreprocessorTests {
|
||||
|
||||
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
||||
});
|
||||
|
||||
@Test
|
||||
public void modifyRequestContent() {
|
||||
void modifyRequestContent() {
|
||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
"content".getBytes(), new HttpHeaders(), Collections.<OperationRequestPart>emptyList());
|
||||
OperationRequest preprocessed = this.preprocessor.preprocess(request);
|
||||
@@ -64,7 +64,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modifyResponseContent() {
|
||||
void modifyResponseContent() {
|
||||
OperationResponse response = this.responseFactory.create(HttpStatus.OK, new HttpHeaders(),
|
||||
"content".getBytes());
|
||||
OperationResponse preprocessed = this.preprocessor.preprocess(response);
|
||||
@@ -72,7 +72,7 @@ public class ContentModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentLengthIsUpdated() {
|
||||
void contentLengthIsUpdated() {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentLength(7);
|
||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost"), HttpMethod.GET,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.restdocs.operation.preprocess;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
|
||||
@@ -31,10 +31,10 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class DelegatingOperationRequestPreprocessorTests {
|
||||
class DelegatingOperationRequestPreprocessorTests {
|
||||
|
||||
@Test
|
||||
public void delegationOccurs() {
|
||||
void delegationOccurs() {
|
||||
OperationRequest originalRequest = mock(OperationRequest.class);
|
||||
OperationPreprocessor preprocessor1 = mock(OperationPreprocessor.class);
|
||||
OperationRequest preprocessedRequest1 = mock(OperationRequest.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.restdocs.operation.preprocess;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
|
||||
@@ -31,10 +31,10 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class DelegatingOperationResponsePreprocessorTests {
|
||||
class DelegatingOperationResponsePreprocessorTests {
|
||||
|
||||
@Test
|
||||
public void delegationOccurs() {
|
||||
void delegationOccurs() {
|
||||
OperationResponse originalResponse = mock(OperationResponse.class);
|
||||
OperationPreprocessor preprocessor1 = mock(OperationPreprocessor.class);
|
||||
OperationResponse preprocessedResponse1 = mock(OperationResponse.class);
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -41,12 +41,12 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
* @author Jihoon Cha
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class HeadersModifyingOperationPreprocessorTests {
|
||||
class HeadersModifyingOperationPreprocessorTests {
|
||||
|
||||
private final HeadersModifyingOperationPreprocessor preprocessor = new HeadersModifyingOperationPreprocessor();
|
||||
|
||||
@Test
|
||||
public void addNewHeader() {
|
||||
void addNewHeader() {
|
||||
this.preprocessor.add("a", "alpha");
|
||||
assertThat(this.preprocessor.preprocess(createRequest()).getHeaders().get("a"))
|
||||
.isEqualTo(Arrays.asList("alpha"));
|
||||
@@ -55,7 +55,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addValueToExistingHeader() {
|
||||
void addValueToExistingHeader() {
|
||||
this.preprocessor.add("a", "alpha");
|
||||
assertThat(this.preprocessor.preprocess(createRequest((headers) -> headers.add("a", "apple")))
|
||||
.getHeaders()
|
||||
@@ -66,7 +66,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNewHeader() {
|
||||
void setNewHeader() {
|
||||
this.preprocessor.set("a", "alpha", "avocado");
|
||||
assertThat(this.preprocessor.preprocess(createRequest()).getHeaders().headerSet())
|
||||
.contains(entry("a", Arrays.asList("alpha", "avocado")));
|
||||
@@ -75,7 +75,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setExistingHeader() {
|
||||
void setExistingHeader() {
|
||||
this.preprocessor.set("a", "alpha", "avocado");
|
||||
assertThat(this.preprocessor.preprocess(createRequest((headers) -> headers.add("a", "apple")))
|
||||
.getHeaders()
|
||||
@@ -86,14 +86,14 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeNonExistentHeader() {
|
||||
void removeNonExistentHeader() {
|
||||
this.preprocessor.remove("a");
|
||||
assertThat(this.preprocessor.preprocess(createRequest()).getHeaders().headerNames()).doesNotContain("a");
|
||||
assertThat(this.preprocessor.preprocess(createResponse()).getHeaders().headerNames()).doesNotContain("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeader() {
|
||||
void removeHeader() {
|
||||
this.preprocessor.remove("a");
|
||||
assertThat(this.preprocessor.preprocess(createRequest((headers) -> headers.add("a", "apple")))
|
||||
.getHeaders()
|
||||
@@ -104,14 +104,14 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeaderValueForNonExistentHeader() {
|
||||
void removeHeaderValueForNonExistentHeader() {
|
||||
this.preprocessor.remove("a", "apple");
|
||||
assertThat(this.preprocessor.preprocess(createRequest()).getHeaders().headerNames()).doesNotContain("a");
|
||||
assertThat(this.preprocessor.preprocess(createResponse()).getHeaders().headerNames()).doesNotContain("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeaderValueWithMultipleValues() {
|
||||
void removeHeaderValueWithMultipleValues() {
|
||||
this.preprocessor.remove("a", "apple");
|
||||
assertThat(
|
||||
this.preprocessor.preprocess(createRequest((headers) -> headers.addAll("a", List.of("apple", "alpha"))))
|
||||
@@ -125,7 +125,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeaderValueWithSingleValueRemovesEntryEntirely() {
|
||||
void removeHeaderValueWithSingleValueRemovesEntryEntirely() {
|
||||
this.preprocessor.remove("a", "apple");
|
||||
assertThat(this.preprocessor.preprocess(createRequest((headers) -> headers.add("a", "apple")))
|
||||
.getHeaders()
|
||||
@@ -136,7 +136,7 @@ public class HeadersModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeadersByNamePattern() {
|
||||
void removeHeadersByNamePattern() {
|
||||
Consumer<HttpHeaders> headersCustomizer = (headers) -> {
|
||||
headers.add("apple", "apple");
|
||||
headers.add("alpha", "alpha");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.hypermedia.Link;
|
||||
|
||||
@@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class LinkMaskingContentModifierTests {
|
||||
class LinkMaskingContentModifierTests {
|
||||
|
||||
private final ContentModifier contentModifier = new LinkMaskingContentModifier();
|
||||
|
||||
@@ -47,38 +47,38 @@ public class LinkMaskingContentModifierTests {
|
||||
private final Link[] maskedLinks = new Link[] { new Link("a", "..."), new Link("b", "...") };
|
||||
|
||||
@Test
|
||||
public void halLinksAreMasked() throws Exception {
|
||||
void halLinksAreMasked() throws Exception {
|
||||
assertThat(this.contentModifier.modifyContent(halPayloadWithLinks(this.links), null))
|
||||
.isEqualTo(halPayloadWithLinks(this.maskedLinks));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formattedHalLinksAreMasked() throws Exception {
|
||||
void formattedHalLinksAreMasked() throws Exception {
|
||||
assertThat(this.contentModifier.modifyContent(formattedHalPayloadWithLinks(this.links), null))
|
||||
.isEqualTo(formattedHalPayloadWithLinks(this.maskedLinks));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomLinksAreMasked() throws Exception {
|
||||
void atomLinksAreMasked() throws Exception {
|
||||
assertThat(this.contentModifier.modifyContent(atomPayloadWithLinks(this.links), null))
|
||||
.isEqualTo(atomPayloadWithLinks(this.maskedLinks));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formattedAtomLinksAreMasked() throws Exception {
|
||||
void formattedAtomLinksAreMasked() throws Exception {
|
||||
assertThat(this.contentModifier.modifyContent(formattedAtomPayloadWithLinks(this.links), null))
|
||||
.isEqualTo(formattedAtomPayloadWithLinks(this.maskedLinks));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maskCanBeCustomized() throws Exception {
|
||||
void maskCanBeCustomized() throws Exception {
|
||||
assertThat(
|
||||
new LinkMaskingContentModifier("custom").modifyContent(formattedAtomPayloadWithLinks(this.links), null))
|
||||
.isEqualTo(formattedAtomPayloadWithLinks(new Link("a", "custom"), new Link("b", "custom")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void maskCanUseUtf8Characters() throws Exception {
|
||||
void maskCanUseUtf8Characters() throws Exception {
|
||||
String ellipsis = "\u2026";
|
||||
assertThat(
|
||||
new LinkMaskingContentModifier(ellipsis).modifyContent(formattedHalPayloadWithLinks(this.links), null))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
@@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PatternReplacingContentModifierTests {
|
||||
class PatternReplacingContentModifierTests {
|
||||
|
||||
@Test
|
||||
public void patternsAreReplaced() {
|
||||
void patternsAreReplaced() {
|
||||
Pattern pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier(pattern, "<<uuid>>");
|
||||
@@ -44,7 +44,7 @@ public class PatternReplacingContentModifierTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void contentThatDoesNotMatchIsUnchanged() {
|
||||
void contentThatDoesNotMatchIsUnchanged() {
|
||||
Pattern pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier(pattern, "<<uuid>>");
|
||||
@@ -53,7 +53,7 @@ public class PatternReplacingContentModifierTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingIsPreservedUsingCharsetFromContentType() {
|
||||
void encodingIsPreservedUsingCharsetFromContentType() {
|
||||
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
||||
Pattern pattern = Pattern.compile("[0-9]+");
|
||||
PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier(pattern, "<<number>>");
|
||||
@@ -63,7 +63,7 @@ public class PatternReplacingContentModifierTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingIsPreservedUsingFallbackCharset() {
|
||||
void encodingIsPreservedUsingFallbackCharset() {
|
||||
String japaneseContent = "\u30b3\u30f3\u30c6\u30f3\u30c4";
|
||||
Pattern pattern = Pattern.compile("[0-9]+");
|
||||
PatternReplacingContentModifier contentModifier = new PatternReplacingContentModifier(pattern, "<<number>>",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,10 +20,11 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.restdocs.testfixtures.OutputCaptureRule;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.CapturedOutput;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OutputCaptureExtension;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -33,19 +34,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class PrettyPrintingContentModifierTests {
|
||||
|
||||
@Rule
|
||||
public OutputCaptureRule outputCapture = new OutputCaptureRule();
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class PrettyPrintingContentModifierTests {
|
||||
|
||||
@Test
|
||||
public void prettyPrintJson() {
|
||||
void prettyPrintJson() {
|
||||
assertThat(new PrettyPrintingContentModifier().modifyContent("{\"a\":5}".getBytes(), null))
|
||||
.isEqualTo(String.format("{%n \"a\" : 5%n}").getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prettyPrintXml() {
|
||||
void prettyPrintXml() {
|
||||
assertThat(new PrettyPrintingContentModifier()
|
||||
.modifyContent("<one a=\"alpha\"><two b=\"bravo\"/></one>".getBytes(), null))
|
||||
.isEqualTo(String
|
||||
@@ -55,28 +54,28 @@ public class PrettyPrintingContentModifierTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empytContentIsHandledGracefully() {
|
||||
void empytContentIsHandledGracefully() {
|
||||
assertThat(new PrettyPrintingContentModifier().modifyContent("".getBytes(), null)).isEqualTo("".getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonJsonAndNonXmlContentIsHandledGracefully() {
|
||||
void nonJsonAndNonXmlContentIsHandledGracefully(CapturedOutput output) {
|
||||
String content = "abcdefg";
|
||||
assertThat(new PrettyPrintingContentModifier().modifyContent(content.getBytes(), null))
|
||||
.isEqualTo(content.getBytes());
|
||||
assertThat(this.outputCapture).isEmpty();
|
||||
assertThat(output).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonJsonContentThatInitiallyLooksLikeJsonIsHandledGracefully() {
|
||||
void nonJsonContentThatInitiallyLooksLikeJsonIsHandledGracefully(CapturedOutput output) {
|
||||
String content = "\"abc\",\"def\"";
|
||||
assertThat(new PrettyPrintingContentModifier().modifyContent(content.getBytes(), null))
|
||||
.isEqualTo(content.getBytes());
|
||||
assertThat(this.outputCapture).isEmpty();
|
||||
assertThat(output).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingIsPreserved() throws Exception {
|
||||
void encodingIsPreserved() throws Exception {
|
||||
Map<String, String> input = new HashMap<>();
|
||||
input.put("japanese", "\u30b3\u30f3\u30c6\u30f3\u30c4");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -41,7 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class UriModifyingOperationPreprocessorTests {
|
||||
class UriModifyingOperationPreprocessorTests {
|
||||
|
||||
private final OperationRequestFactory requestFactory = new OperationRequestFactory();
|
||||
|
||||
@@ -50,14 +50,14 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
private final UriModifyingOperationPreprocessor preprocessor = new UriModifyingOperationPreprocessor();
|
||||
|
||||
@Test
|
||||
public void requestUriSchemeCanBeModified() {
|
||||
void requestUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithUri("http://localhost:12345"));
|
||||
assertThat(processed.getUri()).isEqualTo(URI.create("https://localhost:12345"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriHostCanBeModified() {
|
||||
void requestUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithUri("https://api.foo.com:12345"));
|
||||
assertThat(processed.getUri()).isEqualTo(URI.create("https://api.example.com:12345"));
|
||||
@@ -65,7 +65,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPortCanBeModified() {
|
||||
void requestUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("https://api.example.com:12345"));
|
||||
@@ -74,7 +74,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPortCanBeRemoved() {
|
||||
void requestUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("https://api.example.com:12345"));
|
||||
@@ -83,7 +83,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriPathIsPreserved() {
|
||||
void requestUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("https://api.example.com:12345/foo/bar"));
|
||||
@@ -91,7 +91,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriQueryIsPreserved() {
|
||||
void requestUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("https://api.example.com:12345?foo=bar"));
|
||||
@@ -99,7 +99,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUriAnchorIsPreserved() {
|
||||
void requestUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("https://api.example.com:12345#foo"));
|
||||
@@ -107,7 +107,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriSchemeCanBeModified() {
|
||||
void requestContentUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithContent(
|
||||
"The uri 'https://localhost:12345' should be used. foo:bar will be unaffected"));
|
||||
@@ -116,7 +116,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriHostCanBeModified() {
|
||||
void requestContentUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithContent(
|
||||
"The uri 'https://localhost:12345' should be used. foo:bar will be unaffected"));
|
||||
@@ -125,7 +125,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentHostOfUriWithoutPortCanBeModified() {
|
||||
void requestContentHostOfUriWithoutPortCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationRequest processed = this.preprocessor.preprocess(
|
||||
createRequestWithContent("The uri 'https://localhost' should be used. foo:bar will be unaffected"));
|
||||
@@ -134,7 +134,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPortCanBeAdded() {
|
||||
void requestContentUriPortCanBeAdded() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationRequest processed = this.preprocessor.preprocess(
|
||||
createRequestWithContent("The uri 'http://localhost' should be used. foo:bar will be unaffected"));
|
||||
@@ -143,7 +143,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPortCanBeModified() {
|
||||
void requestContentUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithContent(
|
||||
"The uri 'http://localhost:12345' should be used. foo:bar will be unaffected"));
|
||||
@@ -152,7 +152,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPortCanBeRemoved() {
|
||||
void requestContentUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithContent(
|
||||
"The uri 'http://localhost:12345' should be used. foo:bar will be unaffected"));
|
||||
@@ -161,7 +161,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleRequestContentUrisCanBeModified() {
|
||||
void multipleRequestContentUrisCanBeModified() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor.preprocess(createRequestWithContent(
|
||||
"Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
|
||||
@@ -170,7 +170,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriPathIsPreserved() {
|
||||
void requestContentUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345/foo/bar' should be used"));
|
||||
@@ -178,7 +178,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriQueryIsPreserved() {
|
||||
void requestContentUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345?foo=bar' should be used"));
|
||||
@@ -186,7 +186,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestContentUriAnchorIsPreserved() {
|
||||
void requestContentUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithContent("The uri 'http://localhost:12345#foo' should be used"));
|
||||
@@ -194,7 +194,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriSchemeCanBeModified() {
|
||||
void responseContentUriSchemeCanBeModified() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
@@ -202,7 +202,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriHostCanBeModified() {
|
||||
void responseContentUriHostCanBeModified() {
|
||||
this.preprocessor.host("api.example.com");
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'https://localhost:12345' should be used"));
|
||||
@@ -211,7 +211,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPortCanBeModified() {
|
||||
void responseContentUriPortCanBeModified() {
|
||||
this.preprocessor.port(23456);
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
@@ -219,7 +219,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPortCanBeRemoved() {
|
||||
void responseContentUriPortCanBeRemoved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345' should be used"));
|
||||
@@ -227,7 +227,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleResponseContentUrisCanBeModified() {
|
||||
void multipleResponseContentUrisCanBeModified() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor.preprocess(createResponseWithContent(
|
||||
"Use 'http://localhost:12345' or 'https://localhost:23456' to access the service"));
|
||||
@@ -236,7 +236,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriPathIsPreserved() {
|
||||
void responseContentUriPathIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345/foo/bar' should be used"));
|
||||
@@ -244,7 +244,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriQueryIsPreserved() {
|
||||
void responseContentUriQueryIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345?foo=bar' should be used"));
|
||||
@@ -252,7 +252,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseContentUriAnchorIsPreserved() {
|
||||
void responseContentUriAnchorIsPreserved() {
|
||||
this.preprocessor.removePort();
|
||||
OperationResponse processed = this.preprocessor
|
||||
.preprocess(createResponseWithContent("The uri 'http://localhost:12345#foo' should be used"));
|
||||
@@ -260,7 +260,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestHeadersCanBeModified() {
|
||||
void urisInRequestHeadersCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createRequestWithHeader("Foo", "https://locahost:12345"));
|
||||
assertThat(processed.getHeaders().getFirst("Foo")).isEqualTo("https://api.example.com:12345");
|
||||
@@ -268,14 +268,14 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInResponseHeadersCanBeModified() {
|
||||
void urisInResponseHeadersCanBeModified() {
|
||||
OperationResponse processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createResponseWithHeader("Foo", "https://locahost:12345"));
|
||||
assertThat(processed.getHeaders().getFirst("Foo")).isEqualTo("https://api.example.com:12345");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestPartHeadersCanBeModified() {
|
||||
void urisInRequestPartHeadersCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createRequestWithPartWithHeader("Foo", "https://locahost:12345"));
|
||||
assertThat(processed.getParts().iterator().next().getHeaders().getFirst("Foo"))
|
||||
@@ -283,7 +283,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urisInRequestPartContentCanBeModified() {
|
||||
void urisInRequestPartContentCanBeModified() {
|
||||
OperationRequest processed = this.preprocessor.host("api.example.com")
|
||||
.preprocess(createRequestWithPartWithContent("The uri 'https://localhost:12345' should be used"));
|
||||
assertThat(new String(processed.getParts().iterator().next().getContent()))
|
||||
@@ -291,7 +291,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modifiedUriDoesNotGetDoubleEncoded() {
|
||||
void modifiedUriDoesNotGetDoubleEncoded() {
|
||||
this.preprocessor.scheme("https");
|
||||
OperationRequest processed = this.preprocessor
|
||||
.preprocess(createRequestWithUri("http://localhost:12345?foo=%7B%7D"));
|
||||
@@ -300,7 +300,7 @@ public class UriModifyingOperationPreprocessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resultingRequestHasCookiesFromOriginalRequst() {
|
||||
void resultingRequestHasCookiesFromOriginalRequst() {
|
||||
List<RequestCookie> cookies = Arrays.asList(new RequestCookie("a", "alpha"));
|
||||
OperationRequest request = this.requestFactory.create(URI.create("http://localhost:12345"), HttpMethod.GET,
|
||||
new byte[0], new HttpHeaders(), Collections.<OperationRequestPart>emptyList(), cookies);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,21 +19,13 @@ package org.springframework.restdocs.payload;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.GeneratedSnippets;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest.Format;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
@@ -41,33 +33,17 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class AsciidoctorRequestFieldsSnippetTests {
|
||||
class AsciidoctorRequestFieldsSnippetTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public GeneratedSnippets generatedSnippets = new GeneratedSnippets(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithListDescription() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields"))
|
||||
.willReturn(snippetResource("request-fields-with-list-description"));
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description(Arrays.asList("one", "two")))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("{\"a\": \"foo\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(SnippetConditions.tableWithHeader(TemplateFormats.asciidoctor(), "Path", "Type", "Description")
|
||||
//
|
||||
.row("a", "String", String.format(" - one%n - two"))
|
||||
.configuration("[cols=\"1,1,1a\"]"));
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name) {
|
||||
return new FileSystemResource("src/test/resources/custom-snippet-templates/asciidoctor/" + name + ".snippet");
|
||||
@RenderedSnippetTest(format = Format.ASCIIDOCTOR)
|
||||
@SnippetTemplate(snippet = "request-fields", template = "request-fields-with-list-description")
|
||||
void requestFieldsWithListDescription(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description(Arrays.asList("one", "two"))))
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": \"foo\"}").build());
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("a", "String", String.format(" - one%n - two"))
|
||||
.configuration("[cols=\"1,1,1a\"]"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
@@ -38,11 +38,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class FieldPathPayloadSubsectionExtractorTests {
|
||||
class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMapSubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
|
||||
void extractMapSubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.b")
|
||||
.extractSubsection("{\"a\":{\"b\":{\"c\":5}}}".getBytes(), MediaType.APPLICATION_JSON);
|
||||
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
|
||||
@@ -52,8 +52,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractSingleElementArraySubsectionOfJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
void extractSingleElementArraySubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[]")
|
||||
.extractSubsection("{\"a\":[{\"b\":5}]}".getBytes(), MediaType.APPLICATION_JSON);
|
||||
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
|
||||
@@ -63,8 +62,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMultiElementArraySubsectionOfJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
void extractMultiElementArraySubsectionOfJsonMap() throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a")
|
||||
.extractSubsection("{\"a\":[{\"b\":5},{\"b\":4}]}".getBytes(), MediaType.APPLICATION_JSON);
|
||||
Map<String, Object> extracted = new ObjectMapper().readValue(extractedPayload, Map.class);
|
||||
@@ -74,7 +72,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMapSubsectionFromSingleElementArrayInAJsonMap()
|
||||
void extractMapSubsectionFromSingleElementArrayInAJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b")
|
||||
.extractSubsection("{\"a\":[{\"b\":{\"c\":5}}]}".getBytes(), MediaType.APPLICATION_JSON);
|
||||
@@ -85,7 +83,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMapSubsectionWithCommonStructureFromMultiElementArrayInAJsonMap()
|
||||
void extractMapSubsectionWithCommonStructureFromMultiElementArrayInAJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b")
|
||||
.extractSubsection("{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6}}]}".getBytes(), MediaType.APPLICATION_JSON);
|
||||
@@ -95,7 +93,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractMapSubsectionWithVaryingStructureFromMultiElementArrayInAJsonMap() {
|
||||
void extractMapSubsectionWithVaryingStructureFromMultiElementArrayInAJsonMap() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a.[].b").extractSubsection(
|
||||
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": 7}}]}".getBytes(), MediaType.APPLICATION_JSON))
|
||||
@@ -103,7 +101,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMap() {
|
||||
void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMap() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new FieldPathPayloadSubsectionExtractor("*.d").extractSubsection(
|
||||
"{\"a\":{\"b\":1},\"c\":{\"d\":{\"e\":1,\"f\":2}}}".getBytes(), MediaType.APPLICATION_JSON))
|
||||
@@ -111,7 +109,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMapWhereAllSubsectionFieldsAreOptional() {
|
||||
void extractMapSubsectionWithVaryingStructureFromInconsistentJsonMapWhereAllSubsectionFieldsAreOptional() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new FieldPathPayloadSubsectionExtractor("*.d").extractSubsection(
|
||||
"{\"a\":{\"b\":1},\"c\":{\"d\":{\"e\":1,\"f\":2}}}".getBytes(), MediaType.APPLICATION_JSON,
|
||||
@@ -121,7 +119,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMapSubsectionWithVaryingStructureDueToOptionalFieldsFromMultiElementArrayInAJsonMap()
|
||||
void extractMapSubsectionWithVaryingStructureDueToOptionalFieldsFromMultiElementArrayInAJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b").extractSubsection(
|
||||
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": 7}}]}".getBytes(), MediaType.APPLICATION_JSON,
|
||||
@@ -133,7 +131,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void extractMapSubsectionWithVaryingStructureDueToOptionalParentFieldsFromMultiElementArrayInAJsonMap()
|
||||
void extractMapSubsectionWithVaryingStructureDueToOptionalParentFieldsFromMultiElementArrayInAJsonMap()
|
||||
throws JsonParseException, JsonMappingException, IOException {
|
||||
byte[] extractedPayload = new FieldPathPayloadSubsectionExtractor("a.[].b").extractSubsection(
|
||||
"{\"a\":[{\"b\":{\"c\":5}},{\"b\":{\"c\":6, \"d\": { \"e\": 7}}}]}".getBytes(),
|
||||
@@ -144,7 +142,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractedSubsectionIsPrettyPrintedWhenInputIsPrettyPrinted()
|
||||
void extractedSubsectionIsPrettyPrintedWhenInputIsPrettyPrinted()
|
||||
throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
|
||||
byte[] prettyPrintedPayload = objectMapper
|
||||
@@ -157,7 +155,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractedSubsectionIsNotPrettyPrintedWhenInputIsNotPrettyPrinted()
|
||||
void extractedSubsectionIsNotPrettyPrintedWhenInputIsNotPrettyPrinted()
|
||||
throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
byte[] payload = objectMapper
|
||||
@@ -169,7 +167,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractNonExistentSubsection() {
|
||||
void extractNonExistentSubsection() {
|
||||
assertThatThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a.c")
|
||||
.extractSubsection("{\"a\":{\"b\":{\"c\":5}}}".getBytes(), MediaType.APPLICATION_JSON))
|
||||
.isInstanceOf(PayloadHandlingException.class)
|
||||
@@ -177,7 +175,7 @@ public class FieldPathPayloadSubsectionExtractorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractEmptyArraySubsection() {
|
||||
void extractEmptyArraySubsection() {
|
||||
assertThatThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a")
|
||||
.extractSubsection("{\"a\":[]}}".getBytes(), MediaType.APPLICATION_JSON))
|
||||
.isInstanceOf(PayloadHandlingException.class)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Andy Wilkinson
|
||||
* @author Mathias Düsterhöft
|
||||
*/
|
||||
public class JsonContentHandlerTests {
|
||||
class JsonContentHandlerTests {
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNullValueMustMatch() {
|
||||
void typeForFieldWithNullValueMustMatch() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a").type(JsonFieldType.STRING);
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new JsonContentHandler("{\"a\": null}".getBytes(), Arrays.asList(descriptor))
|
||||
@@ -42,7 +42,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNotNullAndThenNullValueMustMatch() {
|
||||
void typeForFieldWithNotNullAndThenNullValueMustMatch() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a[].id").type(JsonFieldType.STRING);
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class).isThrownBy(
|
||||
() -> new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}".getBytes(), Arrays.asList(descriptor))
|
||||
@@ -50,7 +50,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNullAndThenNotNullValueMustMatch() {
|
||||
void typeForFieldWithNullAndThenNotNullValueMustMatch() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a.[].id").type(JsonFieldType.STRING);
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class).isThrownBy(
|
||||
() -> new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(), Arrays.asList(descriptor))
|
||||
@@ -58,7 +58,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForOptionalFieldWithNumberAndThenNullValueIsNumber() {
|
||||
void typeForOptionalFieldWithNumberAndThenNullValueIsNumber() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a[].id").optional();
|
||||
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(),
|
||||
Arrays.asList(descriptor))
|
||||
@@ -67,7 +67,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForOptionalFieldWithNullAndThenNumberIsNumber() {
|
||||
void typeForOptionalFieldWithNullAndThenNumberIsNumber() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a[].id").optional();
|
||||
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(),
|
||||
Arrays.asList(descriptor))
|
||||
@@ -76,7 +76,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNumberAndThenNullValueIsVaries() {
|
||||
void typeForFieldWithNumberAndThenNullValueIsVaries() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a[].id");
|
||||
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":1},{\"id\":null}]}\"".getBytes(),
|
||||
Arrays.asList(descriptor))
|
||||
@@ -85,7 +85,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithNullAndThenNumberIsVaries() {
|
||||
void typeForFieldWithNullAndThenNumberIsVaries() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a[].id");
|
||||
Object fieldType = new JsonContentHandler("{\"a\":[{\"id\":null},{\"id\":1}]}".getBytes(),
|
||||
Arrays.asList(descriptor))
|
||||
@@ -94,7 +94,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForOptionalFieldWithNullValueCanBeProvidedExplicitly() {
|
||||
void typeForOptionalFieldWithNullValueCanBeProvidedExplicitly() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a").type(JsonFieldType.STRING).optional();
|
||||
Object fieldType = new JsonContentHandler("{\"a\": null}".getBytes(), Arrays.asList(descriptor))
|
||||
.resolveFieldType(descriptor);
|
||||
@@ -102,7 +102,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeForFieldWithSometimesPresentOptionalAncestorCanBeProvidedExplicitly() {
|
||||
void typeForFieldWithSometimesPresentOptionalAncestorCanBeProvidedExplicitly() {
|
||||
FieldDescriptor descriptor = new FieldDescriptor("a.[].b.c").type(JsonFieldType.NUMBER);
|
||||
FieldDescriptor ancestor = new FieldDescriptor("a.[].b").optional();
|
||||
Object fieldType = new JsonContentHandler("{\"a\":[ { \"d\": 4}, {\"b\":{\"c\":5}, \"d\": 4}]}".getBytes(),
|
||||
@@ -112,13 +112,13 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failsFastWithNonJsonContent() {
|
||||
void failsFastWithNonJsonContent() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new JsonContentHandler("Non-JSON content".getBytes(), Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentIsConsideredMissing() {
|
||||
void describedFieldThatIsNotPresentIsConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"),
|
||||
new FieldDescriptor("c"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes(),
|
||||
@@ -129,7 +129,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
void describedOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a"), new FieldDescriptor("b"),
|
||||
new FieldDescriptor("c").optional());
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\": \"alpha\", \"b\":\"bravo\"}".getBytes(),
|
||||
@@ -139,7 +139,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsPresentIsConsideredMissing() {
|
||||
void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsPresentIsConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"),
|
||||
new FieldDescriptor("a.c"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\":\"alpha\",\"b\":\"bravo\"}".getBytes(),
|
||||
@@ -150,7 +150,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
void describedFieldThatIsNotPresentNestedBeneathOptionalFieldThatIsNotPresentIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a").optional(), new FieldDescriptor("b"),
|
||||
new FieldDescriptor("a.c"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"b\":\"bravo\"}".getBytes(), descriptors)
|
||||
@@ -159,7 +159,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedFieldThatIsNotPresentNestedBeneathOptionalArrayThatIsEmptyIsNotConsideredMissing() {
|
||||
void describedFieldThatIsNotPresentNestedBeneathOptionalArrayThatIsEmptyIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("outer"),
|
||||
new FieldDescriptor("outer[]").optional(), new FieldDescriptor("outer[].inner"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"outer\":[]}".getBytes(), descriptors)
|
||||
@@ -168,7 +168,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedSometimesPresentFieldThatIsChildOfSometimesPresentOptionalArrayIsNotConsideredMissing() {
|
||||
void describedSometimesPresentFieldThatIsChildOfSometimesPresentOptionalArrayIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a.[].c").optional(),
|
||||
new FieldDescriptor("a.[].c.d"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler(
|
||||
@@ -178,7 +178,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatIsEmptyIsNotConsideredMissing() {
|
||||
void describedMissingFieldThatIsChildOfNestedOptionalArrayThatIsEmptyIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a.[].b").optional(),
|
||||
new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\":[{\"b\":[]}]}".getBytes(), descriptors)
|
||||
@@ -187,7 +187,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedMissingFieldThatIsChildOfNestedOptionalArrayThatContainsAnObjectIsConsideredMissing() {
|
||||
void describedMissingFieldThatIsChildOfNestedOptionalArrayThatContainsAnObjectIsConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a.[].b").optional(),
|
||||
new FieldDescriptor("a.[].b.[]").optional(), new FieldDescriptor("a.[].b.[].c"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\":[{\"b\":[{}]}]}".getBytes(), descriptors)
|
||||
@@ -197,7 +197,7 @@ public class JsonContentHandlerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void describedMissingFieldThatIsChildOfOptionalObjectThatIsNullIsNotConsideredMissing() {
|
||||
void describedMissingFieldThatIsChildOfOptionalObjectThatIsNullIsNotConsideredMissing() {
|
||||
List<FieldDescriptor> descriptors = Arrays.asList(new FieldDescriptor("a").optional(),
|
||||
new FieldDescriptor("a.b"));
|
||||
List<FieldDescriptor> missingFields = new JsonContentHandler("{\"a\":null}".getBytes(), descriptors)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldPath.PathType;
|
||||
|
||||
@@ -28,131 +28,131 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
* @author Jeremy Rickard
|
||||
*/
|
||||
public class JsonFieldPathTests {
|
||||
class JsonFieldPathTests {
|
||||
|
||||
@Test
|
||||
public void pathTypeOfSingleFieldIsSingle() {
|
||||
void pathTypeOfSingleFieldIsSingle() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a");
|
||||
assertThat(path.getType()).isEqualTo(PathType.SINGLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfSingleNestedFieldIsSingle() {
|
||||
void pathTypeOfSingleNestedFieldIsSingle() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a.b");
|
||||
assertThat(path.getType()).isEqualTo(PathType.SINGLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfTopLevelArrayIsSingle() {
|
||||
void pathTypeOfTopLevelArrayIsSingle() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("[]");
|
||||
assertThat(path.getType()).isEqualTo(PathType.SINGLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfFieldBeneathTopLevelArrayIsMulti() {
|
||||
void pathTypeOfFieldBeneathTopLevelArrayIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("[]a");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfSingleNestedArrayIsSingle() {
|
||||
void pathTypeOfSingleNestedArrayIsSingle() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a[]");
|
||||
assertThat(path.getType()).isEqualTo(PathType.SINGLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfArrayBeneathNestedFieldsIsSingle() {
|
||||
void pathTypeOfArrayBeneathNestedFieldsIsSingle() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a.b[]");
|
||||
assertThat(path.getType()).isEqualTo(PathType.SINGLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfArrayOfArraysIsMulti() {
|
||||
void pathTypeOfArrayOfArraysIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a[][]");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfFieldBeneathAnArrayIsMulti() {
|
||||
void pathTypeOfFieldBeneathAnArrayIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a[].b");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfFieldBeneathTopLevelWildcardIsMulti() {
|
||||
void pathTypeOfFieldBeneathTopLevelWildcardIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("*.a");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfFieldBeneathNestedWildcardIsMulti() {
|
||||
void pathTypeOfFieldBeneathNestedWildcardIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a.*.b");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathTypeOfLeafWidlcardIsMulti() {
|
||||
void pathTypeOfLeafWidlcardIsMulti() {
|
||||
JsonFieldPath path = JsonFieldPath.compile("a.*");
|
||||
assertThat(path.getType()).isEqualTo(PathType.MULTI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfSingleElementPath() {
|
||||
void compilationOfSingleElementPath() {
|
||||
assertThat(JsonFieldPath.compile("a").getSegments()).containsExactly("a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfMultipleElementPath() {
|
||||
void compilationOfMultipleElementPath() {
|
||||
assertThat(JsonFieldPath.compile("a.b.c").getSegments()).containsExactly("a", "b", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithArraysWithNoDotSeparators() {
|
||||
void compilationOfPathWithArraysWithNoDotSeparators() {
|
||||
assertThat(JsonFieldPath.compile("a[]b[]c").getSegments()).containsExactly("a", "[]", "b", "[]", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithArraysWithPreAndPostDotSeparators() {
|
||||
void compilationOfPathWithArraysWithPreAndPostDotSeparators() {
|
||||
assertThat(JsonFieldPath.compile("a.[].b.[].c").getSegments()).containsExactly("a", "[]", "b", "[]", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithArraysWithPreDotSeparators() {
|
||||
void compilationOfPathWithArraysWithPreDotSeparators() {
|
||||
assertThat(JsonFieldPath.compile("a.[]b.[]c").getSegments()).containsExactly("a", "[]", "b", "[]", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithArraysWithPostDotSeparators() {
|
||||
void compilationOfPathWithArraysWithPostDotSeparators() {
|
||||
assertThat(JsonFieldPath.compile("a[].b[].c").getSegments()).containsExactly("a", "[]", "b", "[]", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathStartingWithAnArray() {
|
||||
void compilationOfPathStartingWithAnArray() {
|
||||
assertThat(JsonFieldPath.compile("[]a.b.c").getSegments()).containsExactly("[]", "a", "b", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfMultipleElementPathWithBrackets() {
|
||||
void compilationOfMultipleElementPathWithBrackets() {
|
||||
assertThat(JsonFieldPath.compile("['a']['b']['c']").getSegments()).containsExactly("a", "b", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfMultipleElementPathWithAndWithoutBrackets() {
|
||||
void compilationOfMultipleElementPathWithAndWithoutBrackets() {
|
||||
assertThat(JsonFieldPath.compile("['a'][].b['c']").getSegments()).containsExactly("a", "[]", "b", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfMultipleElementPathWithAndWithoutBracketsAndEmbeddedDots() {
|
||||
void compilationOfMultipleElementPathWithAndWithoutBracketsAndEmbeddedDots() {
|
||||
assertThat(JsonFieldPath.compile("['a.key'][].b['c']").getSegments()).containsExactly("a.key", "[]", "b", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithAWildcard() {
|
||||
void compilationOfPathWithAWildcard() {
|
||||
assertThat(JsonFieldPath.compile("a.b.*.c").getSegments()).containsExactly("a", "b", "*", "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilationOfPathWithAWildcardInBrackets() {
|
||||
void compilationOfPathWithAWildcardInBrackets() {
|
||||
assertThat(JsonFieldPath.compile("a.b.['*'].c").getSegments()).containsExactly("a", "b", "*", "c");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
|
||||
|
||||
@@ -31,10 +31,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldPathsTests {
|
||||
class JsonFieldPathsTests {
|
||||
|
||||
@Test
|
||||
public void noUncommonPathsForSingleItem() {
|
||||
void noUncommonPathsForSingleItem() {
|
||||
assertThat(
|
||||
JsonFieldPaths.from(Arrays.asList(json("{\"a\": 1, \"b\": [ { \"c\": 2}, {\"c\": 3}, {\"c\": null}]}")))
|
||||
.getUncommon())
|
||||
@@ -42,20 +42,20 @@ public class JsonFieldPathsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noUncommonPathsForMultipleIdenticalItems() {
|
||||
void noUncommonPathsForMultipleIdenticalItems() {
|
||||
Object item = json("{\"a\": 1, \"b\": [ { \"c\": 2}, {\"c\": 3} ]}");
|
||||
assertThat(JsonFieldPaths.from(Arrays.asList(item, item)).getUncommon()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noUncommonPathsForMultipleMatchingItemsWithDifferentScalarValues() {
|
||||
void noUncommonPathsForMultipleMatchingItemsWithDifferentScalarValues() {
|
||||
assertThat(JsonFieldPaths.from(Arrays.asList(json("{\"a\": 1, \"b\": [ { \"c\": 2}, {\"c\": 3} ]}"),
|
||||
json("{\"a\": 4, \"b\": [ { \"c\": 5}, {\"c\": 6} ]}")))
|
||||
.getUncommon()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingEntryInMapIsIdentifiedAsUncommon() {
|
||||
void missingEntryInMapIsIdentifiedAsUncommon() {
|
||||
assertThat(
|
||||
JsonFieldPaths.from(Arrays.asList(json("{\"a\": 1}"), json("{\"a\": 1}"), json("{\"a\": 1, \"b\": 2}")))
|
||||
.getUncommon())
|
||||
@@ -63,21 +63,21 @@ public class JsonFieldPathsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingEntryInNestedMapIsIdentifiedAsUncommon() {
|
||||
void missingEntryInNestedMapIsIdentifiedAsUncommon() {
|
||||
assertThat(JsonFieldPaths.from(Arrays.asList(json("{\"a\": 1, \"b\": {\"c\": 1}}"),
|
||||
json("{\"a\": 1, \"b\": {\"c\": 1}}"), json("{\"a\": 1, \"b\": {\"c\": 1, \"d\": 2}}")))
|
||||
.getUncommon()).containsExactly("b.d");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingEntriesInNestedMapAreIdentifiedAsUncommon() {
|
||||
void missingEntriesInNestedMapAreIdentifiedAsUncommon() {
|
||||
assertThat(JsonFieldPaths.from(Arrays.asList(json("{\"a\": 1, \"b\": {\"c\": 1}}"),
|
||||
json("{\"a\": 1, \"b\": {\"c\": 1}}"), json("{\"a\": 1, \"b\": {\"d\": 2}}")))
|
||||
.getUncommon()).containsExactly("b.c", "b.d");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absentItemFromFieldExtractionCausesAllPresentFieldsToBeIdentifiedAsUncommon() {
|
||||
void absentItemFromFieldExtractionCausesAllPresentFieldsToBeIdentifiedAsUncommon() {
|
||||
assertThat(JsonFieldPaths
|
||||
.from(Arrays.asList(ExtractedField.ABSENT, json("{\"a\": 1, \"b\": {\"c\": 1}}"),
|
||||
json("{\"a\": 1, \"b\": {\"c\": 1}}"), json("{\"a\": 1, \"b\": {\"d\": 2}}")))
|
||||
@@ -85,14 +85,14 @@ public class JsonFieldPathsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingEntryBeneathArrayIsIdentifiedAsUncommon() {
|
||||
void missingEntryBeneathArrayIsIdentifiedAsUncommon() {
|
||||
assertThat(JsonFieldPaths
|
||||
.from(Arrays.asList(json("[{\"b\": 1}]"), json("[{\"b\": 1}]"), json("[{\"b\": 1, \"c\": 2}]")))
|
||||
.getUncommon()).containsExactly("[].c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingEntryBeneathNestedArrayIsIdentifiedAsUncommon() {
|
||||
void missingEntryBeneathNestedArrayIsIdentifiedAsUncommon() {
|
||||
assertThat(JsonFieldPaths.from(Arrays.asList(json("{\"a\": [{\"b\": 1}]}"), json("{\"a\": [{\"b\": 1}]}"),
|
||||
json("{\"a\": [{\"b\": 1, \"c\": 2}]}")))
|
||||
.getUncommon()).containsExactly("a.[].c");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.payload.JsonFieldProcessor.ExtractedField;
|
||||
|
||||
@@ -37,19 +37,19 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldProcessorTests {
|
||||
class JsonFieldProcessorTests {
|
||||
|
||||
private final JsonFieldProcessor fieldProcessor = new JsonFieldProcessor();
|
||||
|
||||
@Test
|
||||
public void extractTopLevelMapEntry() {
|
||||
void extractTopLevelMapEntry() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", "alpha");
|
||||
assertThat(this.fieldProcessor.extract("a", payload).getValue()).isEqualTo("alpha");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractNestedMapEntry() {
|
||||
void extractNestedMapEntry() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -58,7 +58,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractTopLevelArray() {
|
||||
void extractTopLevelArray() {
|
||||
List<Map<String, Object>> payload = new ArrayList<>();
|
||||
Map<String, Object> bravo = new HashMap<>();
|
||||
bravo.put("b", "bravo");
|
||||
@@ -68,7 +68,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractArray() {
|
||||
void extractArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> bravo = new HashMap<>();
|
||||
bravo.put("b", "bravo");
|
||||
@@ -78,7 +78,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractArrayContents() {
|
||||
void extractArrayContents() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> bravo = new HashMap<>();
|
||||
bravo.put("b", "bravo");
|
||||
@@ -88,7 +88,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractFromItemsInArray() {
|
||||
void extractFromItemsInArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> entry = new HashMap<>();
|
||||
entry.put("b", "bravo");
|
||||
@@ -98,7 +98,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractOccasionallyAbsentFieldFromItemsInArray() {
|
||||
void extractOccasionallyAbsentFieldFromItemsInArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> entry = new HashMap<>();
|
||||
entry.put("b", "bravo");
|
||||
@@ -109,7 +109,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractOccasionallyNullFieldFromItemsInArray() {
|
||||
void extractOccasionallyNullFieldFromItemsInArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> nonNullField = new HashMap<>();
|
||||
nonNullField.put("b", "bravo");
|
||||
@@ -121,7 +121,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractNestedArray() {
|
||||
void extractNestedArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, String> entry1 = createEntry("id:1");
|
||||
Map<String, String> entry2 = createEntry("id:2");
|
||||
@@ -133,7 +133,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractFromItemsInNestedArray() {
|
||||
void extractFromItemsInNestedArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, String> entry1 = createEntry("id:1");
|
||||
Map<String, String> entry2 = createEntry("id:2");
|
||||
@@ -144,7 +144,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractArraysFromItemsInNestedArray() {
|
||||
void extractArraysFromItemsInNestedArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> entry1 = createEntry("ids", Arrays.asList(1, 2));
|
||||
Map<String, Object> entry2 = createEntry("ids", Arrays.asList(3));
|
||||
@@ -156,27 +156,27 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentTopLevelField() {
|
||||
void nonExistentTopLevelField() {
|
||||
assertThat(this.fieldProcessor.extract("a", Collections.emptyMap()).getValue())
|
||||
.isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentNestedField() {
|
||||
void nonExistentNestedField() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", new HashMap<String, Object>());
|
||||
payload.put("a", new HashMap<>());
|
||||
assertThat(this.fieldProcessor.extract("a.b", payload).getValue()).isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentNestedFieldWhenParentIsNotAMap() {
|
||||
void nonExistentNestedFieldWhenParentIsNotAMap() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", 5);
|
||||
assertThat(this.fieldProcessor.extract("a.b", payload).getValue()).isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentFieldWhenParentIsAnArray() {
|
||||
void nonExistentFieldWhenParentIsAnArray() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
HashMap<String, Object> alpha = new HashMap<>();
|
||||
alpha.put("b", Arrays.asList(new HashMap<String, Object>()));
|
||||
@@ -185,20 +185,20 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentArrayField() {
|
||||
void nonExistentArrayField() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
assertThat(this.fieldProcessor.extract("a[]", payload).getValue()).isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentArrayFieldAsTypeDoesNotMatch() {
|
||||
void nonExistentArrayFieldAsTypeDoesNotMatch() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", 5);
|
||||
assertThat(this.fieldProcessor.extract("a[]", payload).getValue()).isEqualTo(ExtractedField.ABSENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentFieldBeneathAnArray() {
|
||||
void nonExistentFieldBeneathAnArray() {
|
||||
HashMap<String, Object> payload = new HashMap<>();
|
||||
HashMap<String, Object> alpha = new HashMap<>();
|
||||
alpha.put("b", Arrays.asList(new HashMap<String, Object>()));
|
||||
@@ -208,7 +208,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeTopLevelMapEntry() {
|
||||
void removeTopLevelMapEntry() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", "alpha");
|
||||
this.fieldProcessor.remove("a", payload);
|
||||
@@ -216,7 +216,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapWithEntriesIsNotRemovedWhenNotAlsoRemovingDescendants() {
|
||||
void mapWithEntriesIsNotRemovedWhenNotAlsoRemovingDescendants() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -226,7 +226,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeSubsectionRemovesMapWithEntries() {
|
||||
void removeSubsectionRemovesMapWithEntries() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -236,7 +236,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeNestedMapEntry() {
|
||||
void removeNestedMapEntry() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -247,7 +247,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeItemsInArray() throws IOException {
|
||||
void removeItemsInArray() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [{\"b\":\"bravo\"},{\"b\":\"bravo\"}]}",
|
||||
Map.class);
|
||||
this.fieldProcessor.remove("a[].b", payload);
|
||||
@@ -256,7 +256,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeItemsInNestedArray() throws IOException {
|
||||
void removeItemsInNestedArray() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [[{\"id\":1},{\"id\":2}], [{\"id\":3}]]}",
|
||||
Map.class);
|
||||
this.fieldProcessor.remove("a[][].id", payload);
|
||||
@@ -265,7 +265,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeDoesNotRemoveArrayWithMapEntries() throws IOException {
|
||||
void removeDoesNotRemoveArrayWithMapEntries() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [{\"b\":\"bravo\"},{\"b\":\"bravo\"}]}",
|
||||
Map.class);
|
||||
this.fieldProcessor.remove("a[]", payload);
|
||||
@@ -274,7 +274,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeDoesNotRemoveArrayWithListEntries() throws IOException {
|
||||
void removeDoesNotRemoveArrayWithListEntries() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [[2],[3]]}", Map.class);
|
||||
this.fieldProcessor.remove("a[]", payload);
|
||||
assertThat(payload.size()).isEqualTo(1);
|
||||
@@ -282,7 +282,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeRemovesArrayWithOnlyScalarEntries() throws IOException {
|
||||
void removeRemovesArrayWithOnlyScalarEntries() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [\"bravo\", \"charlie\"]}", Map.class);
|
||||
this.fieldProcessor.remove("a", payload);
|
||||
assertThat(payload.size()).isEqualTo(0);
|
||||
@@ -290,7 +290,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeSubsectionRemovesArrayWithMapEntries() throws IOException {
|
||||
void removeSubsectionRemovesArrayWithMapEntries() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [{\"b\":\"bravo\"},{\"b\":\"bravo\"}]}",
|
||||
Map.class);
|
||||
this.fieldProcessor.removeSubsection("a[]", payload);
|
||||
@@ -299,14 +299,14 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void removeSubsectionRemovesArrayWithListEntries() throws IOException {
|
||||
void removeSubsectionRemovesArrayWithListEntries() throws IOException {
|
||||
Map<String, Object> payload = new ObjectMapper().readValue("{\"a\": [[2],[3]]}", Map.class);
|
||||
this.fieldProcessor.removeSubsection("a[]", payload);
|
||||
assertThat(payload.size()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extractNestedEntryWithDotInKeys() {
|
||||
void extractNestedEntryWithDotInKeys() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a.key", alpha);
|
||||
@@ -316,7 +316,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void extractNestedEntriesUsingTopLevelWildcard() {
|
||||
void extractNestedEntriesUsingTopLevelWildcard() {
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
Map<String, Object> alpha = new LinkedHashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -330,7 +330,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void extractNestedEntriesUsingMidLevelWildcard() {
|
||||
void extractNestedEntriesUsingMidLevelWildcard() {
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
Map<String, Object> alpha = new LinkedHashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -344,7 +344,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void extractUsingLeafWildcardMatchingSingleItem() {
|
||||
void extractUsingLeafWildcardMatchingSingleItem() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -357,7 +357,7 @@ public class JsonFieldProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void extractUsingLeafWildcardMatchingMultipleItems() {
|
||||
void extractUsingLeafWildcardMatchingMultipleItems() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -368,7 +368,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeUsingLeafWildcard() {
|
||||
void removeUsingLeafWildcard() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -379,7 +379,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeUsingTopLevelWildcard() {
|
||||
void removeUsingTopLevelWildcard() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> alpha = new HashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -390,7 +390,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeUsingMidLevelWildcard() {
|
||||
void removeUsingMidLevelWildcard() {
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
Map<String, Object> alpha = new LinkedHashMap<>();
|
||||
payload.put("a", alpha);
|
||||
@@ -407,28 +407,28 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsTrueForNonNullFieldInMap() {
|
||||
void hasFieldIsTrueForNonNullFieldInMap() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", "alpha");
|
||||
assertThat(this.fieldProcessor.hasField("a", payload)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsTrueForNullFieldInMap() {
|
||||
void hasFieldIsTrueForNullFieldInMap() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", null);
|
||||
assertThat(this.fieldProcessor.hasField("a", payload)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsFalseForAbsentFieldInMap() {
|
||||
void hasFieldIsFalseForAbsentFieldInMap() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("a", null);
|
||||
assertThat(this.fieldProcessor.hasField("b", payload)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsTrueForNeverNullFieldBeneathArray() {
|
||||
void hasFieldIsTrueForNeverNullFieldBeneathArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> nested = new HashMap<>();
|
||||
nested.put("b", "bravo");
|
||||
@@ -437,7 +437,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsTrueForAlwaysNullFieldBeneathArray() {
|
||||
void hasFieldIsTrueForAlwaysNullFieldBeneathArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> nested = new HashMap<>();
|
||||
nested.put("b", null);
|
||||
@@ -446,7 +446,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsFalseForAlwaysAbsentFieldBeneathArray() {
|
||||
void hasFieldIsFalseForAlwaysAbsentFieldBeneathArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> nested = new HashMap<>();
|
||||
nested.put("b", "bravo");
|
||||
@@ -455,7 +455,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsFalseForOccasionallyAbsentFieldBeneathArray() {
|
||||
void hasFieldIsFalseForOccasionallyAbsentFieldBeneathArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> nested = new HashMap<>();
|
||||
nested.put("b", "bravo");
|
||||
@@ -464,7 +464,7 @@ public class JsonFieldProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasFieldIsFalseForOccasionallyNullFieldBeneathArray() {
|
||||
void hasFieldIsFalseForOccasionallyNullFieldBeneathArray() {
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
Map<String, Object> fieldPresent = new HashMap<>();
|
||||
fieldPresent.put("b", "bravo");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.payload;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@@ -29,148 +29,148 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldTypesDiscovererTests {
|
||||
class JsonFieldTypesDiscovererTests {
|
||||
|
||||
private final JsonFieldTypesDiscoverer fieldTypeDiscoverer = new JsonFieldTypesDiscoverer();
|
||||
|
||||
@Test
|
||||
public void arrayField() throws IOException {
|
||||
void arrayField() throws IOException {
|
||||
assertThat(discoverFieldTypes("[]")).containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void topLevelArray() throws IOException {
|
||||
void topLevelArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("[]", "[{\"a\":\"alpha\"}]")).containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedArray() throws IOException {
|
||||
void nestedArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[]", "{\"a\": [{\"b\":\"bravo\"}]}")).containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayNestedBeneathAnArray() throws IOException {
|
||||
void arrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].b[]", "{\"a\": [{\"b\": [ 1, 2 ]}]}")).containsExactly(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void specificFieldOfObjectInArrayNestedBeneathAnArray() throws IOException {
|
||||
void specificFieldOfObjectInArrayNestedBeneathAnArray() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].b[].c", "{\"a\": [{\"b\": [ {\"c\": 5}, {\"c\": 5}]}]}"))
|
||||
.containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void booleanField() throws IOException {
|
||||
void booleanField() throws IOException {
|
||||
assertThat(discoverFieldTypes("true")).containsExactly(JsonFieldType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectField() throws IOException {
|
||||
void objectField() throws IOException {
|
||||
assertThat(discoverFieldTypes("{}")).containsExactly(JsonFieldType.OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullField() throws IOException {
|
||||
void nullField() throws IOException {
|
||||
assertThat(discoverFieldTypes("null")).containsExactly(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numberField() throws IOException {
|
||||
void numberField() throws IOException {
|
||||
assertThat(discoverFieldTypes("1.2345")).containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringField() throws IOException {
|
||||
void stringField() throws IOException {
|
||||
assertThat(discoverFieldTypes("\"Foo\"")).containsExactly(JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedField() throws IOException {
|
||||
void nestedField() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.b.c", "{\"a\":{\"b\":{\"c\":{}}}}")).containsExactly(JsonFieldType.OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithSameType() throws IOException {
|
||||
void multipleFieldsWithSameType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":2}]}"))
|
||||
.containsExactly(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypes() throws IOException {
|
||||
void multipleFieldsWithDifferentTypes() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":true}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
|
||||
void multipleFieldsWithDifferentTypesAndSometimesAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":true}, {}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.BOOLEAN, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesAbsent() throws IOException {
|
||||
void multipleFieldsWhenSometimesAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":2}, {}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenSometimesNull() throws IOException {
|
||||
void multipleFieldsWhenSometimesNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":2}, {\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
|
||||
void multipleFieldsWithDifferentTypesAndSometimesNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":1},{\"id\":true}, {\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.BOOLEAN, JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
|
||||
void multipleFieldsWhenEitherNullOrAbsent() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{},{\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleFieldsThatAreAllNull() throws IOException {
|
||||
void multipleFieldsThatAreAllNull() throws IOException {
|
||||
assertThat(discoverFieldTypes("a[].id", "{\"a\":[{\"id\":null},{\"id\":null}]}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NULL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentSingleFieldProducesFieldDoesNotExistException() {
|
||||
void nonExistentSingleFieldProducesFieldDoesNotExistException() {
|
||||
assertThatExceptionOfType(FieldDoesNotExistException.class)
|
||||
.isThrownBy(() -> discoverFieldTypes("a.b", "{\"a\":{}}"))
|
||||
.withMessage("The payload does not contain a field with the path 'a.b'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonExistentMultipleFieldsProducesFieldDoesNotExistException() {
|
||||
void nonExistentMultipleFieldsProducesFieldDoesNotExistException() {
|
||||
assertThatExceptionOfType(FieldDoesNotExistException.class)
|
||||
.isThrownBy(() -> discoverFieldTypes("a[].b", "{\"a\":[{\"c\":1},{\"c\":2}]}"))
|
||||
.withMessage("The payload does not contain a field with the path 'a[].b'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithCommonType() throws IOException {
|
||||
void leafWildcardWithCommonType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*", "{\"a\": {\"b\": 5, \"c\": 6}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leafWildcardWithVaryingType() throws IOException {
|
||||
void leafWildcardWithVaryingType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*", "{\"a\": {\"b\": 5, \"c\": \"six\"}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithCommonType() throws IOException {
|
||||
void intermediateWildcardWithCommonType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*.d", "{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": 5}}}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intermediateWildcardWithVaryingType() throws IOException {
|
||||
void intermediateWildcardWithVaryingType() throws IOException {
|
||||
assertThat(discoverFieldTypes("a.*.d", "{\"a\": {\"b\": {\"d\": 4}, \"c\": {\"d\": \"four\"}}}}"))
|
||||
.containsExactlyInAnyOrder(JsonFieldType.NUMBER, JsonFieldType.STRING);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -27,32 +27,32 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JsonFieldTypesTests {
|
||||
class JsonFieldTypesTests {
|
||||
|
||||
@Test
|
||||
public void singleTypeCoalescesToThatType() {
|
||||
void singleTypeCoalescesToThatType() {
|
||||
assertThat(new JsonFieldTypes(JsonFieldType.NUMBER).coalesce(false)).isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleTypeCoalescesToThatTypeWhenOptional() {
|
||||
void singleTypeCoalescesToThatTypeWhenOptional() {
|
||||
assertThat(new JsonFieldTypes(JsonFieldType.NUMBER).coalesce(true)).isEqualTo(JsonFieldType.NUMBER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleTypesCoalescesToVaries() {
|
||||
void multipleTypesCoalescesToVaries() {
|
||||
assertThat(new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NUMBER)).coalesce(false))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndNonNullTypesCoalescesToVaries() {
|
||||
void nullAndNonNullTypesCoalescesToVaries() {
|
||||
assertThat(new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NULL)).coalesce(false))
|
||||
.isEqualTo(JsonFieldType.VARIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAndNonNullTypesCoalescesToNonNullTypeWhenOptional() {
|
||||
void nullAndNonNullTypesCoalescesToNonNullTypeWhenOptional() {
|
||||
assertThat(new JsonFieldTypes(EnumSet.of(JsonFieldType.ARRAY, JsonFieldType.NULL)).coalesce(true))
|
||||
.isEqualTo(JsonFieldType.ARRAY);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.payload;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.applyPathPrefix;
|
||||
@@ -31,10 +31,10 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PayloadDocumentationTests {
|
||||
class PayloadDocumentationTests {
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixAppliesPrefixToDescriptorPaths() {
|
||||
void applyPathPrefixAppliesPrefixToDescriptorPaths() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.",
|
||||
Arrays.asList(fieldWithPath("bravo"), fieldWithPath("charlie")));
|
||||
assertThat(descriptors.size()).isEqualTo(2);
|
||||
@@ -42,21 +42,21 @@ public class PayloadDocumentationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixCopiesIgnored() {
|
||||
void applyPathPrefixCopiesIgnored() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.", Arrays.asList(fieldWithPath("bravo").ignored()));
|
||||
assertThat(descriptors.size()).isEqualTo(1);
|
||||
assertThat(descriptors.get(0).isIgnored()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixCopiesOptional() {
|
||||
void applyPathPrefixCopiesOptional() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.", Arrays.asList(fieldWithPath("bravo").optional()));
|
||||
assertThat(descriptors.size()).isEqualTo(1);
|
||||
assertThat(descriptors.get(0).isOptional()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixCopiesDescription() {
|
||||
void applyPathPrefixCopiesDescription() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.",
|
||||
Arrays.asList(fieldWithPath("bravo").description("Some field")));
|
||||
assertThat(descriptors.size()).isEqualTo(1);
|
||||
@@ -64,7 +64,7 @@ public class PayloadDocumentationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixCopiesType() {
|
||||
void applyPathPrefixCopiesType() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.",
|
||||
Arrays.asList(fieldWithPath("bravo").type(JsonFieldType.OBJECT)));
|
||||
assertThat(descriptors.size()).isEqualTo(1);
|
||||
@@ -72,7 +72,7 @@ public class PayloadDocumentationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyPathPrefixCopiesAttributes() {
|
||||
void applyPathPrefixCopiesAttributes() {
|
||||
List<FieldDescriptor> descriptors = applyPathPrefix("alpha.",
|
||||
Arrays.asList(fieldWithPath("bravo").attributes(key("a").value("alpha"), key("b").value("bravo"))));
|
||||
assertThat(descriptors.size()).isEqualTo(1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,14 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.requestPartBody;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
@@ -41,89 +36,84 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestBodyPartSnippetTests extends AbstractSnippetTests {
|
||||
class RequestBodyPartSnippetTests {
|
||||
|
||||
public RequestBodyPartSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithBody() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestPartBody("one")
|
||||
.document(this.operationBuilder.request("http://localhost").part("one", "some content".getBytes()).build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock(null, "nowrap").withContent("some content"));
|
||||
.document(operationBuilder.request("http://localhost").part("one", "some content".getBytes()).build());
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("some content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithNoBody() throws IOException {
|
||||
requestPartBody("one")
|
||||
.document(this.operationBuilder.request("http://localhost").part("one", new byte[0]).build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock(null, "nowrap").withContent(""));
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithNoBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestPartBody("one").document(operationBuilder.request("http://localhost").part("one", new byte[0]).build());
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithJsonMediaType() throws IOException {
|
||||
requestPartBody("one").document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithJsonMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestPartBody("one").document(operationBuilder.request("http://localhost")
|
||||
.part("one", "".getBytes())
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock("json", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithJsonSubtypeMediaType() throws IOException {
|
||||
requestPartBody("one").document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithJsonSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestPartBody("one").document(operationBuilder.request("http://localhost")
|
||||
.part("one", "".getBytes())
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PROBLEM_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock("json", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithXmlMediaType() throws IOException {
|
||||
requestPartBody("one").document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithXmlMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestPartBody("one").document(operationBuilder.request("http://localhost")
|
||||
.part("one", "".getBytes())
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock("xml", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartWithXmlSubtypeMediaType() throws IOException {
|
||||
requestPartBody("one").document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestPartWithXmlSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestPartBody("one").document(operationBuilder.request("http://localhost")
|
||||
.part("one", "".getBytes())
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_ATOM_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock("xml", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestPartBody("one"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfRequestPartBody() throws IOException {
|
||||
requestPartBody("one", beneathPath("a.b")).document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfRequestPartBody(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestPartBody("one", beneathPath("a.b")).document(operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\":{\"b\":{\"c\":5}}}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body-beneath-a.b"))
|
||||
.is(codeBlock(null, "nowrap").withContent("{\"c\":5}"));
|
||||
assertThat(snippets.requestPartBody("one", "beneath-a.b"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("{\"c\":5}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-part-body"))
|
||||
.willReturn(snippetResource("request-part-body-with-language"));
|
||||
requestPartBody("one", attributes(key("language").value("json"))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.part("one", "{\"a\":\"alpha\"}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-body"))
|
||||
.is(codeBlock("json", "nowrap").withContent("{\"a\":\"alpha\"}"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-part-body", template = "request-part-body-with-language")
|
||||
void customSnippetAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestPartBody("one", attributes(key("language").value("json")))
|
||||
.document(operationBuilder.request("http://localhost").part("one", "{\"a\":\"alpha\"}".getBytes()).build());
|
||||
assertThat(snippets.requestPartBody("one")).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content("{\"a\":\"alpha\"}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,14 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.requestBody;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
@@ -41,77 +36,74 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestBodySnippetTests extends AbstractSnippetTests {
|
||||
class RequestBodySnippetTests {
|
||||
|
||||
public RequestBodySnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
@RenderedSnippetTest
|
||||
void requestWithBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost").content("some content").build());
|
||||
assertThat(snippets.requestBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("some content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithBody() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost").content("some content").build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body"))
|
||||
.is(codeBlock(null, "nowrap").withContent("some content"));
|
||||
@RenderedSnippetTest
|
||||
void requestWithNoBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost").build());
|
||||
assertThat(snippets.requestBody()).isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithNoBody() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost").build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body")).is(codeBlock(null, "nowrap").withContent(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithJsonMediaType() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestWithJsonMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body")).is(codeBlock("json", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithJsonSubtypeMediaType() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestWithJsonSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PROBLEM_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body")).is(codeBlock("json", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithXmlMediaType() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestWithXmlMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body")).is(codeBlock("xml", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithXmlSubtypeMediaType() throws IOException {
|
||||
requestBody().document(this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void requestWithXmlSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestBody().document(operationBuilder.request("http://localhost")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_ATOM_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body")).is(codeBlock("xml", "nowrap").withContent(""));
|
||||
assertThat(snippets.requestBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfRequestBody() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfRequestBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody(beneathPath("a.b"))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\":{\"b\":{\"c\":5}}}").build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body-beneath-a.b"))
|
||||
.is(codeBlock(null, "nowrap").withContent("{\"c\":5}"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\":{\"b\":{\"c\":5}}}").build());
|
||||
assertThat(snippets.requestBody("beneath-a.b"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("{\"c\":5}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-body"))
|
||||
.willReturn(snippetResource("request-body-with-language"));
|
||||
requestBody(attributes(key("language").value("json"))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("{\"a\":\"alpha\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-body"))
|
||||
.is(codeBlock("json", "nowrap").withContent("{\"a\":\"alpha\"}"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-body", template = "request-body-with-language")
|
||||
void customSnippetAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestBody(attributes(key("language").value("json")))
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\":\"alpha\"}").build());
|
||||
assertThat(snippets.requestBody()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content("{\"a\":\"alpha\"}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestFieldsSnippet} due to missing or
|
||||
* undocumented fields.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestFieldsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": 5}").build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{}").build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a.b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalRequestFieldWithNoTypeProvided() {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class).isThrownBy(
|
||||
() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one").optional()))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{ }").build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestFieldAndMissingRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{ \"a\": { \"c\": 5 }}").build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a.b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attemptToDocumentFieldsWithNoRequestBody() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Cannot document request fields as the request body is empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitTypeThatDoesNotMatchThePayload() {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{ \"a\": 5 }").build()))
|
||||
.withMessage("The documented type of the field 'a' is Object but the actual type is Number");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitSpecificTypeThatActuallyVaries() {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("[].a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("[{ \"a\": 5 },{ \"a\": \"b\" }]")
|
||||
.build()))
|
||||
.withMessage("The documented type of the field '[].a' is Object but the actual type is Varies");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlDescendentsAreNotDocumentedByFieldDescriptor() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").type("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlRequestFieldWithNoType() {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a/b").description("one"), fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlRequestFieldAndMissingXmlRequestField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsupportedContent() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("Some plain text")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
|
||||
.build()))
|
||||
.withMessage("Cannot handle text/plain content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOptionalFieldBeneathArrayThatIsSometimesNull() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"b\": null, \"c\": 2}," + " {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOptionalFieldBeneathArrayThatIsSometimesAbsent() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,21 +18,19 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
|
||||
@@ -46,342 +44,492 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andy Wilkinson
|
||||
* @author Sungjun Lee
|
||||
*/
|
||||
public class RequestFieldsSnippetTests extends AbstractSnippetTests {
|
||||
class RequestFieldsSnippetTests {
|
||||
|
||||
public RequestFieldsSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestWithFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapRequestWithFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one"),
|
||||
fieldWithPath("a.c").description("two"), fieldWithPath("a").description("three")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestWithNullField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapRequestWithNullField(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": {\"b\": null}}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Null`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": {\"b\": null}}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`Null`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entireSubsectionsCanBeDocumented() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void entireSubsectionsCanBeDocumented(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(subsectionWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Object`", "one"));
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`Object`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfMapRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfMapRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestFields(beneathPath("a"), fieldWithPath("b").description("one"), fieldWithPath("c").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-fields-beneath-a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "one")
|
||||
assertThat(snippets.requestFields("beneath-a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "one")
|
||||
.row("`c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfMapRequestWithCommonPrefix() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfMapRequestWithCommonPrefix(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
requestFields(beneathPath("a")).andWithPrefix("b.", fieldWithPath("c").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": {\"c\": \"charlie\"}}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-fields-beneath-a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b.c`", "`String`", "two"));
|
||||
assertThat(snippets.requestFields("beneath-a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b.c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayRequestWithFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void arrayRequestWithFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("[]").description("one"), fieldWithPath("[]a.b").description("two"),
|
||||
fieldWithPath("[]a.c").description("three"), fieldWithPath("[]a").description("four")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("[{\"a\": {\"b\": 5, \"c\":\"charlie\"}}," + "{\"a\": {\"b\": 4, \"c\":\"chalk\"}}]")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`[]`", "`Array`", "one")
|
||||
.row("`[]a.b`", "`Number`", "two")
|
||||
.row("`[]a.c`", "`String`", "three")
|
||||
.row("`[]a`", "`Object`", "four"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`[]`", "`Array`", "one")
|
||||
.row("`[]a.b`", "`Number`", "two")
|
||||
.row("`[]a.c`", "`String`", "three")
|
||||
.row("`[]a`", "`Object`", "four"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayRequestWithAlwaysNullField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void arrayRequestWithAlwaysNullField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("[]a.b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("[{\"a\": {\"b\": null}}," + "{\"a\": {\"b\": null}}]")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`[]a.b`", "`Null`", "one"));
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`[]a.b`", "`Null`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfArrayRequest() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfArrayRequest(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
requestFields(beneathPath("[].a"), fieldWithPath("b").description("one"), fieldWithPath("c").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("[{\"a\": {\"b\": 5, \"c\": \"charlie\"}}]")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-fields-beneath-[].a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "one")
|
||||
assertThat(snippets.requestFields("beneath-[].a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "one")
|
||||
.row("`c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredRequestField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredRequestField(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").ignored(), fieldWithPath("b").description("Field b")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entireSubsectionCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void entireSubsectionCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(subsectionWithPath("a").ignored(), fieldWithPath("c").description("Field c")))
|
||||
.document(
|
||||
this.operationBuilder.request("http://localhost").content("{\"a\": {\"b\": 5}, \"c\": 4}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`c`", "`Number`", "Field c"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": {\"b\": 5}, \"c\": 4}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`c`", "`Number`", "Field c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedRequestFieldsCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedRequestFieldsCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("b").description("Field b")), true)
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedFieldsContinueToBeIgnoredAfterAddingDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedFieldsContinueToBeIgnoredAfterAddingDescriptors(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("b").description("Field b")), true)
|
||||
.andWithPrefix("c.", fieldWithPath("d").description("Field d"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":5,\"b\":4,\"c\":{\"d\": 3}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b")
|
||||
.row("`c.d`", "`Number`", "Field d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalRequestField() throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingIgnoredOptionalRequestFieldDoesNotRequireAType() throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one").ignored().optional()))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{}").build());
|
||||
assertThat(this.generatedSnippets.requestFields()).is(tableWithHeader("Path", "Type", "Description"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalRequestField() throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(
|
||||
this.operationBuilder.request("http://localhost").content("{\"a\": { \"b\": \"bravo\"}}").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
operationBuilder.request("http://localhost").content("{\"a\":5,\"b\":4,\"c\":{\"d\": 3}}").build());
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "Field b")
|
||||
.row("`c.d`", "`Number`", "Field d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields"))
|
||||
.willReturn(snippetResource("request-fields-with-title"));
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalRequestField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(operationBuilder.request("http://localhost").content("{}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
void missingIgnoredOptionalRequestFieldDoesNotRequireAType(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one").ignored().optional()))
|
||||
.document(operationBuilder.request("http://localhost").content("{}").build());
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalRequestField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": { \"b\": \"bravo\"}}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-fields", template = "request-fields-with-title")
|
||||
void requestFieldsWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("{\"a\": \"foo\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields()).contains("Custom title");
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": \"foo\"}").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withTitleAndHeader("Custom title", "Path", "Type", "Description")
|
||||
.row("a", "String", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-fields"))
|
||||
.willReturn(snippetResource("request-fields-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-fields", template = "request-fields-with-extra-column")
|
||||
void requestFieldsWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").attributes(key("foo").value("alpha")),
|
||||
fieldWithPath("a.c").description("two").attributes(key("foo").value("bravo")),
|
||||
fieldWithPath("a").description("three").attributes(key("foo").value("charlie"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description", "Foo").row("a.b", "Number", "one", "alpha")
|
||||
.row("a.c", "String", "two", "bravo")
|
||||
.row("a", "Object", "three", "charlie"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description", "Foo")
|
||||
.row("a.b", "Number", "one", "alpha")
|
||||
.row("a.c", "String", "two", "bravo")
|
||||
.row("a", "Object", "three", "charlie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitExactlyMatchingType() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void fieldWithExplicitExactlyMatchingType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": 5 }").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Number`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": 5 }").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`Number`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitVariesType() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void fieldWithExplicitVariesType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.VARIES)))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": 5 }").build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Varies`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": 5 }").build());
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`Varies`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationXmlRequestFields() throws IOException {
|
||||
xmlRequestFields(MediaType.APPLICATION_XML);
|
||||
@RenderedSnippetTest
|
||||
void applicationXmlRequestFields(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
xmlRequestFields(MediaType.APPLICATION_XML, operationBuilder, snippets);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textXmlRequestFields() throws IOException {
|
||||
xmlRequestFields(MediaType.TEXT_XML);
|
||||
@RenderedSnippetTest
|
||||
void textXmlRequestFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
xmlRequestFields(MediaType.TEXT_XML, operationBuilder, snippets);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customXmlRequestFields() throws IOException {
|
||||
xmlRequestFields(MediaType.parseMediaType("application/vnd.com.example+xml"));
|
||||
@RenderedSnippetTest
|
||||
void customXmlRequestFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
xmlRequestFields(MediaType.parseMediaType("application/vnd.com.example+xml"), operationBuilder, snippets);
|
||||
}
|
||||
|
||||
private void xmlRequestFields(MediaType contentType) throws IOException {
|
||||
private void xmlRequestFields(MediaType contentType, OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one").type("b"),
|
||||
fieldWithPath("a/c").description("two").type("c"), fieldWithPath("a").description("three").type("a")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, contentType.toString())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a/b`", "`b`", "one")
|
||||
.row("`a/c`", "`c`", "two")
|
||||
.row("`a`", "`a`", "three"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a/b`", "`b`", "one")
|
||||
.row("`a/c`", "`c`", "two")
|
||||
.row("`a`", "`a`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entireSubsectionOfXmlPayloadCanBeDocumented() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void entireSubsectionOfXmlPayloadCanBeDocumented(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(subsectionWithPath("a").description("one").type("a")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`a`", "one"));
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
PayloadDocumentation
|
||||
.requestFields(fieldWithPath("a.b").description("one"), fieldWithPath("a.c").description("two"))
|
||||
.and(fieldWithPath("a").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefixedAdditionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void prefixedAdditionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
PayloadDocumentation.requestFields(fieldWithPath("a").description("one"))
|
||||
.andWithPrefix("a.", fieldWithPath("b").description("two"), fieldWithPath("c").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithFieldsWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithFieldsWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("Foo|Bar").type("one|two").description("three|four")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"Foo|Bar\": 5}").build());
|
||||
assertThat(this.generatedSnippets.requestFields()).is(tableWithHeader("Path", "Type", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("`one|two`"), escapeIfNecessary("three|four")));
|
||||
.document(operationBuilder.request("http://localhost").content("{\"Foo|Bar\": 5}").build());
|
||||
assertThat(snippets.requestFields()).isTable(
|
||||
(table) -> table.withHeader("Path", "Type", "Description").row("`Foo|Bar`", "`one|two`", "three|four"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestWithVaryingKeysMatchedUsingWildcard() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapRequestWithVaryingKeysMatchedUsingWildcard(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(Arrays.asList(fieldWithPath("things.*.size").description("one"),
|
||||
fieldWithPath("things.*.type").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"things\": {\"12abf\": {\"type\":" + "\"Whale\", \"size\": \"HUGE\"},"
|
||||
+ "\"gzM33\" : {\"type\": \"Screw\"," + "\"size\": \"SMALL\"}}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`things.*.size`", "`String`", "one")
|
||||
.row("`things.*.type`", "`String`", "two"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`things.*.size`", "`String`", "one")
|
||||
.row("`things.*.type`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithArrayContainingFieldThatIsSometimesNull() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestWithArrayContainingFieldThatIsSometimesNull(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("assets[].name").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"assets\": [" + "{\"name\": \"sample1\"}, " + "{\"name\": null}, "
|
||||
+ "{\"name\": \"sample2\"}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`assets[].name`", "`String`", "one"));
|
||||
assertThat(snippets.requestFields()).isTable(
|
||||
(table) -> table.withHeader("Path", "Type", "Description").row("`assets[].name`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionalFieldBeneathArrayThatIsSometimesAbsent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void optionalFieldBeneathArrayThatIsSometimesAbsent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER).optional(),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a[].b`", "`Number`", "one")
|
||||
.row("`a[].c`", "`Number`", "two"));
|
||||
assertThat(snippets.requestFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a[].b`", "`Number`", "one")
|
||||
.row("`a[].c`", "`Number`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeDeterminationDoesNotSetTypeOnDescriptor() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void typeDeterminationDoesNotSetTypeOnDescriptor(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
FieldDescriptor descriptor = fieldWithPath("a.b").description("one");
|
||||
new RequestFieldsSnippet(Arrays.asList(descriptor))
|
||||
.document(this.operationBuilder.request("http://localhost").content("{\"a\": {\"b\": 5}}").build());
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": {\"b\": 5}}").build());
|
||||
assertThat(descriptor.getType()).isNull();
|
||||
assertThat(this.generatedSnippets.requestFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one"));
|
||||
assertThat(snippets.requestFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost").content("{\"a\": 5}").build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").content("{}").build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a.b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingOptionalRequestFieldWithNoTypeProvided(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class).isThrownBy(
|
||||
() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one").optional()))
|
||||
.document(operationBuilder.request("http://localhost").content("{ }").build()));
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedRequestFieldAndMissingRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").content("{ \"a\": { \"c\": 5 }}").build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a.b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void attemptToDocumentFieldsWithNoRequestBody(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Cannot document request fields as the request body is empty");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void fieldWithExplicitTypeThatDoesNotMatchThePayload(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(operationBuilder.request("http://localhost").content("{ \"a\": 5 }").build()))
|
||||
.withMessage("The documented type of the field 'a' is Object but the actual type is Number");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void fieldWithExplicitSpecificTypeThatActuallyVaries(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class).isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("[].a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(operationBuilder.request("http://localhost").content("[{ \"a\": 5 },{ \"a\": \"b\" }]").build()))
|
||||
.withMessage("The documented type of the field '[].a' is Object but the actual type is Varies");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedXmlRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void xmlDescendentsAreNotDocumentedByFieldDescriptor(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").type("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void xmlRequestFieldWithNoType(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()));
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingXmlRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a/b").description("one"), fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedXmlRequestFieldAndMissingXmlRequestField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void unsupportedContent(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("Some plain text")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
|
||||
.build()))
|
||||
.withMessage("Cannot handle text/plain content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void nonOptionalFieldBeneathArrayThatIsSometimesNull(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"b\": null, \"c\": 2}," + " {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void nonOptionalFieldBeneathArrayThatIsSometimesAbsent(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestPartFieldsSnippet} due to missing or
|
||||
* undocumented fields.
|
||||
*
|
||||
* @author Mathieu Pousse
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestPartFieldsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedRequestPartField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartFieldsSnippet("part", Collections.<FieldDescriptor>emptyList()).document(
|
||||
this.operationBuilder.request("http://localhost").part("part", "{\"a\": 5}".getBytes()).build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestPartField() {
|
||||
assertThatExceptionOfType(SnippetException.class).isThrownBy(() -> new RequestPartFieldsSnippet("part",
|
||||
Arrays.asList(fieldWithPath("b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").part("part", "{\"a\": 5}".getBytes()).build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestPart() {
|
||||
assertThatExceptionOfType(SnippetException.class).isThrownBy(
|
||||
() -> new RequestPartFieldsSnippet("another", Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.part("part", "{\"a\": {\"b\": 5}}".getBytes())
|
||||
.build()))
|
||||
.withMessage("A request part named 'another' was not found in the request");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,13 +20,15 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
@@ -36,86 +38,110 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit
|
||||
* @author Mathieu Pousse
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestPartFieldsSnippetTests extends AbstractSnippetTests {
|
||||
public class RequestPartFieldsSnippetTests {
|
||||
|
||||
public RequestPartFieldsSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestPartFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapRequestPartFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestPartFieldsSnippet("one",
|
||||
Arrays.asList(fieldWithPath("a.b").description("one"), fieldWithPath("a.c").description("two"),
|
||||
fieldWithPath("a").description("three")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestPartFields("one"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
assertThat(snippets.requestPartFields("one")).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRequestPartSubsectionFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapRequestPartSubsectionFields(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartFieldsSnippet("one", beneathPath("a"),
|
||||
Arrays.asList(fieldWithPath("b").description("one"), fieldWithPath("c").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("request-part-one-fields-beneath-a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "one")
|
||||
assertThat(snippets.requestPartFields("one", "beneath-a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "one")
|
||||
.row("`c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleRequestParts() throws IOException {
|
||||
Operation operation = this.operationBuilder.request("http://localhost")
|
||||
@RenderedSnippetTest
|
||||
void multipleRequestParts(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
Operation operation = operationBuilder.request("http://localhost")
|
||||
.part("one", "{}".getBytes())
|
||||
.and()
|
||||
.part("two", "{}".getBytes())
|
||||
.build();
|
||||
new RequestPartFieldsSnippet("one", Collections.<FieldDescriptor>emptyList()).document(operation);
|
||||
new RequestPartFieldsSnippet("two", Collections.<FieldDescriptor>emptyList()).document(operation);
|
||||
assertThat(this.generatedSnippets.requestPartFields("one")).isNotNull();
|
||||
assertThat(this.generatedSnippets.requestPartFields("two")).isNotNull();
|
||||
assertThat(snippets.requestPartFields("one")).isNotNull();
|
||||
assertThat(snippets.requestPartFields("two")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedRequestPartFieldsCanBeIgnored() throws IOException {
|
||||
new RequestPartFieldsSnippet("one", Arrays.asList(fieldWithPath("b").description("Field b")), true)
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\": 5, \"b\": 4}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestPartFields("one"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedRequestPartFieldsCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartFieldsSnippet("one", Arrays.asList(fieldWithPath("b").description("Field b")), true).document(
|
||||
operationBuilder.request("http://localhost").part("one", "{\"a\": 5, \"b\": 4}".getBytes()).build());
|
||||
assertThat(snippets.requestPartFields("one"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
PayloadDocumentation
|
||||
.requestPartFields("one", fieldWithPath("a.b").description("one"), fieldWithPath("a.c").description("two"))
|
||||
.and(fieldWithPath("a").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestPartFields("one"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
assertThat(snippets.requestPartFields("one")).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a.b`", "`Number`", "one")
|
||||
.row("`a.c`", "`String`", "two")
|
||||
.row("`a`", "`Object`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefixedAdditionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void prefixedAdditionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
PayloadDocumentation.requestPartFields("one", fieldWithPath("a").description("one"))
|
||||
.andWithPrefix("a.", fieldWithPath("b").description("two"), fieldWithPath("c").description("three"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("one", "{\"a\": {\"b\": 5, \"c\": \"charlie\"}}".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestPartFields("one"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
assertThat(snippets.requestPartFields("one")).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedRequestPartField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartFieldsSnippet("part", Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost").part("part", "{\"a\": 5}".getBytes()).build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingRequestPartField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartFieldsSnippet("part", Arrays.asList(fieldWithPath("b").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").part("part", "{\"a\": 5}".getBytes()).build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingRequestPart(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class).isThrownBy(
|
||||
() -> new RequestPartFieldsSnippet("another", Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("part", "{\"a\": {\"b\": 5}}".getBytes())
|
||||
.build()))
|
||||
.withMessage("A request part named 'another' was not found in the request");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,14 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.responseBody;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
@@ -41,77 +36,72 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseBodySnippetTests extends AbstractSnippetTests {
|
||||
class ResponseBodySnippetTests {
|
||||
|
||||
public ResponseBodySnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
@RenderedSnippetTest
|
||||
void responseWithBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseBodySnippet().document(operationBuilder.response().content("some content").build());
|
||||
assertThat(snippets.responseBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("some content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithBody() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response().content("some content").build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body"))
|
||||
.is(codeBlock(null, "nowrap").withContent("some content"));
|
||||
@RenderedSnippetTest
|
||||
void responseWithNoBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseBodySnippet().document(operationBuilder.response().build());
|
||||
assertThat(snippets.responseBody()).isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithNoBody() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response().build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body")).is(codeBlock(null, "nowrap").withContent(""));
|
||||
@RenderedSnippetTest
|
||||
void responseWithJsonMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseBodySnippet().document(
|
||||
operationBuilder.response().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).build());
|
||||
assertThat(snippets.responseBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithJsonMediaType() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body")).is(codeBlock("json", "nowrap").withContent(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithJsonSubtypeMediaType() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response()
|
||||
@RenderedSnippetTest
|
||||
void responseWithJsonSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseBodySnippet().document(operationBuilder.response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PROBLEM_JSON_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body")).is(codeBlock("json", "nowrap").withContent(""));
|
||||
assertThat(snippets.responseBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithXmlMediaType() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body")).is(codeBlock("xml", "nowrap").withContent(""));
|
||||
@RenderedSnippetTest
|
||||
void responseWithXmlMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseBodySnippet().document(
|
||||
operationBuilder.response().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE).build());
|
||||
assertThat(snippets.responseBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithXmlSubtypeMediaType() throws IOException {
|
||||
new ResponseBodySnippet().document(this.operationBuilder.response()
|
||||
@RenderedSnippetTest
|
||||
void responseWithXmlSubtypeMediaType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseBodySnippet().document(operationBuilder.response()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_ATOM_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body")).is(codeBlock("xml", "nowrap").withContent(""));
|
||||
assertThat(snippets.responseBody())
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withLanguageAndOptions("xml", "nowrap").content(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfResponseBody() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfResponseBody(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
responseBody(beneathPath("a.b"))
|
||||
.document(this.operationBuilder.response().content("{\"a\":{\"b\":{\"c\":5}}}").build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body-beneath-a.b"))
|
||||
.is(codeBlock(null, "nowrap").withContent("{\"c\":5}"));
|
||||
.document(operationBuilder.response().content("{\"a\":{\"b\":{\"c\":5}}}").build());
|
||||
assertThat(snippets.responseBody("beneath-a.b"))
|
||||
.isCodeBlock((codeBlock) -> codeBlock.withOptions("nowrap").content("{\"c\":5}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-body"))
|
||||
.willReturn(snippetResource("response-body-with-language"));
|
||||
new ResponseBodySnippet(attributes(key("language").value("json"))).document(
|
||||
this.operationBuilder.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.content("{\"a\":\"alpha\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-body"))
|
||||
.is(codeBlock("json", "nowrap").withContent("{\"a\":\"alpha\"}"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-body", template = "response-body-with-language")
|
||||
void customSnippetAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseBodySnippet(attributes(key("language").value("json")))
|
||||
.document(operationBuilder.response().content("{\"a\":\"alpha\"}").build());
|
||||
assertThat(snippets.responseBody()).isCodeBlock(
|
||||
(codeBlock) -> codeBlock.withLanguageAndOptions("json", "nowrap").content("{\"a\":\"alpha\"}"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.payload;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link ResponseFieldsSnippet} due to missing or
|
||||
* undocumented fields.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ResponseFieldsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void attemptToDocumentFieldsWithNoResponseBody() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.build()))
|
||||
.withMessage("Cannot document response fields as the response body is empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitTypeThatDoesNotMatchThePayload() {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(this.operationBuilder.response().content("{ \"a\": 5 }}").build()))
|
||||
.withMessage("The documented type of the field 'a' is Object but the actual type is Number");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitSpecificTypeThatActuallyVaries() {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("[].a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(this.operationBuilder.response().content("[{ \"a\": 5 },{ \"a\": \"b\" }]").build()))
|
||||
.withMessage("The documented type of the field '[].a' is Object but the actual type is Varies");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlAttribute() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type("b"),
|
||||
fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/@id]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void documentedXmlAttributesAreRemoved() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one").type("a")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage(String.format("The following parts of the payload were not documented:%n<a>bar</a>%n"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlResponseFieldWithNoType() {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingXmlResponseField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a/b").description("one"), fieldWithPath("a").description("one")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedXmlResponseFieldAndMissingXmlResponseField() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsupportedContent() {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(this.operationBuilder.response()
|
||||
.content("Some plain text")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
|
||||
.build()))
|
||||
.withMessage("Cannot handle text/plain content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOptionalFieldBeneathArrayThatIsSometimesNull() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"b\": null, \"c\": 2}," + " {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonOptionalFieldBeneathArrayThatIsSometimesAbsent() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,21 +18,19 @@ package org.springframework.restdocs.payload;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.beneathPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
|
||||
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
|
||||
@@ -45,355 +43,486 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
* @author Andy Wilkinson
|
||||
* @author Sungjun Lee
|
||||
*/
|
||||
public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
|
||||
public class ResponseFieldsSnippetTests {
|
||||
|
||||
public ResponseFieldsSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapResponseWithFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapResponseWithFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("id").description("one"),
|
||||
fieldWithPath("date").description("two"), fieldWithPath("assets").description("three"),
|
||||
fieldWithPath("assets[]").description("four"), fieldWithPath("assets[].id").description("five"),
|
||||
fieldWithPath("assets[].name").description("six")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"id\": 67,\"date\": \"2015-01-20\",\"assets\":" + " [{\"id\":356,\"name\": \"sample\"}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`id`", "`Number`", "one")
|
||||
.row("`date`", "`String`", "two")
|
||||
.row("`assets`", "`Array`", "three")
|
||||
.row("`assets[]`", "`Array`", "four")
|
||||
.row("`assets[].id`", "`Number`", "five")
|
||||
.row("`assets[].name`", "`String`", "six"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`id`", "`Number`", "one")
|
||||
.row("`date`", "`String`", "two")
|
||||
.row("`assets`", "`Array`", "three")
|
||||
.row("`assets[]`", "`Array`", "four")
|
||||
.row("`assets[].id`", "`Number`", "five")
|
||||
.row("`assets[].name`", "`String`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapResponseWithNullField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapResponseWithNullField(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one")))
|
||||
.document(this.operationBuilder.response().content("{\"a\": {\"b\": null}}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`Null`", "one"));
|
||||
.document(operationBuilder.response().content("{\"a\": {\"b\": null}}").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`Null`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfMapResponse() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfMapResponse(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
responseFields(beneathPath("a"), fieldWithPath("b").description("one"), fieldWithPath("c").description("two"))
|
||||
.document(this.operationBuilder.response().content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
assertThat(this.generatedSnippets.snippet("response-fields-beneath-a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "one")
|
||||
.document(operationBuilder.response().content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
assertThat(snippets.responseFields("beneath-a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "one")
|
||||
.row("`c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfMapResponseBeneathAnArray() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfMapResponseBeneathAnArray(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
responseFields(beneathPath("a.b.[]"), fieldWithPath("c").description("one"),
|
||||
fieldWithPath("d.[].e").description("two"))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"a\": {\"b\": [{\"c\": 1, \"d\": [{\"e\": 5}]}, {\"c\": 3, \"d\": [{\"e\": 4}]}]}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.snippet("response-fields-beneath-a.b.[]"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`c`", "`Number`", "one")
|
||||
assertThat(snippets.responseFields("beneath-a.b.[]"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`c`", "`Number`", "one")
|
||||
.row("`d.[].e`", "`Number`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subsectionOfMapResponseWithCommonsPrefix() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void subsectionOfMapResponseWithCommonsPrefix(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
responseFields(beneathPath("a")).andWithPrefix("b.", fieldWithPath("c").description("two"))
|
||||
.document(this.operationBuilder.response().content("{\"a\": {\"b\": {\"c\": \"charlie\"}}}").build());
|
||||
assertThat(this.generatedSnippets.snippet("response-fields-beneath-a"))
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b.c`", "`String`", "two"));
|
||||
.document(operationBuilder.response().content("{\"a\": {\"b\": {\"c\": \"charlie\"}}}").build());
|
||||
assertThat(snippets.responseFields("beneath-a"))
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b.c`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayResponseWithFields() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void arrayResponseWithFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("[]a.b").description("one"),
|
||||
fieldWithPath("[]a.c").description("two"), fieldWithPath("[]a").description("three")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("[{\"a\": {\"b\": 5, \"c\":\"charlie\"}}," + "{\"a\": {\"b\": 4, \"c\":\"chalk\"}}]")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`[]a.b`", "`Number`", "one")
|
||||
.row("`[]a.c`", "`String`", "two")
|
||||
.row("`[]a`", "`Object`", "three"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`[]a.b`", "`Number`", "one")
|
||||
.row("`[]a.c`", "`String`", "two")
|
||||
.row("`[]a`", "`Object`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayResponseWithAlwaysNullField() throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("[]a.b").description("one")))
|
||||
.document(this.operationBuilder.response()
|
||||
.content("[{\"a\": {\"b\": null}}," + "{\"a\": {\"b\": null}}]")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`[]a.b`", "`Null`", "one"));
|
||||
@RenderedSnippetTest
|
||||
void arrayResponseWithAlwaysNullField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("[]a.b").description("one"))).document(
|
||||
operationBuilder.response().content("[{\"a\": {\"b\": null}}," + "{\"a\": {\"b\": null}}]").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`[]a.b`", "`Null`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrayResponse() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void arrayResponse(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("[]").description("one")))
|
||||
.document(this.operationBuilder.response().content("[\"a\", \"b\", \"c\"]").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`[]`", "`Array`", "one"));
|
||||
.document(operationBuilder.response().content("[\"a\", \"b\", \"c\"]").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`[]`", "`Array`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredResponseField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredResponseField(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a").ignored(), fieldWithPath("b").description("Field b")))
|
||||
.document(this.operationBuilder.response().content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
.document(operationBuilder.response().content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedFieldsCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedFieldsCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("b").description("Field b")), true)
|
||||
.document(this.operationBuilder.response().content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
.document(operationBuilder.response().content("{\"a\": 5, \"b\": 4}").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedFieldsContinueToBeIgnoredAfterAddingDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedFieldsContinueToBeIgnoredAfterAddingDescriptors(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("b").description("Field b")), true)
|
||||
.andWithPrefix("c.", fieldWithPath("d").description("Field d"))
|
||||
.document(this.operationBuilder.response().content("{\"a\":5,\"b\":4,\"c\":{\"d\": 3}}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`b`", "`Number`", "Field b")
|
||||
.row("`c.d`", "`Number`", "Field d"));
|
||||
.document(operationBuilder.response().content("{\"a\":5,\"b\":4,\"c\":{\"d\": 3}}").build());
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`b`", "`Number`", "Field b")
|
||||
.row("`c.d`", "`Number`", "Field d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-fields"))
|
||||
.willReturn(snippetResource("response-fields-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-fields", template = "response-fields-with-title")
|
||||
void responseFieldsWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")),
|
||||
attributes(key("title").value("Custom title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.content("{\"a\": \"foo\"}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields()).contains("Custom title");
|
||||
.document(operationBuilder.response().content("{\"a\": \"foo\"}").build());
|
||||
assertThat(snippets.responseFields()).contains("Custom title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalResponseField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalResponseField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(this.operationBuilder.response().content("{}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
.document(operationBuilder.response().content("{}").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingIgnoredOptionalResponseFieldDoesNotRequireAType() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingIgnoredOptionalResponseFieldDoesNotRequireAType(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a.b").description("one").ignored().optional()))
|
||||
.document(this.operationBuilder.response().content("{}").build());
|
||||
assertThat(this.generatedSnippets.responseFields()).is(tableWithHeader("Path", "Type", "Description"));
|
||||
.document(operationBuilder.response().content("{}").build());
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalResponseField() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalResponseField(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(this.operationBuilder.response().content("{\"a\": { \"b\": \"bravo\"}}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
.document(operationBuilder.response().content("{\"a\": { \"b\": \"bravo\"}}").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a.b`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("response-fields"))
|
||||
.willReturn(snippetResource("response-fields-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "response-fields", template = "response-fields-with-extra-column")
|
||||
void responseFieldsWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a.b").description("one").attributes(key("foo").value("alpha")),
|
||||
fieldWithPath("a.c").description("two").attributes(key("foo").value("bravo")),
|
||||
fieldWithPath("a").description("three").attributes(key("foo").value("charlie"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.response()
|
||||
.content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description", "Foo").row("a.b", "Number", "one", "alpha")
|
||||
.row("a.c", "String", "two", "bravo")
|
||||
.row("a", "Object", "three", "charlie"));
|
||||
.document(operationBuilder.response().content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description", "Foo")
|
||||
.row("a.b", "Number", "one", "alpha")
|
||||
.row("a.c", "String", "two", "bravo")
|
||||
.row("a", "Object", "three", "charlie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitExactlyMatchingType() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void fieldWithExplicitExactlyMatchingType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.response().content("{\"a\": 5 }").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Number`", "one"));
|
||||
.document(operationBuilder.response().content("{\"a\": 5 }").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`Number`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldWithExplicitVariesType() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void fieldWithExplicitVariesType(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.VARIES)))
|
||||
.document(this.operationBuilder.response().content("{\"a\": 5 }").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Varies`", "one"));
|
||||
.document(operationBuilder.response().content("{\"a\": 5 }").build());
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`Varies`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applicationXmlResponseFields() throws IOException {
|
||||
xmlResponseFields(MediaType.APPLICATION_XML);
|
||||
@RenderedSnippetTest
|
||||
void applicationXmlResponseFields(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
xmlResponseFields(MediaType.APPLICATION_XML, operationBuilder, snippets);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textXmlResponseFields() throws IOException {
|
||||
xmlResponseFields(MediaType.TEXT_XML);
|
||||
@RenderedSnippetTest
|
||||
void textXmlResponseFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
xmlResponseFields(MediaType.TEXT_XML, operationBuilder, snippets);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customXmlResponseFields() throws IOException {
|
||||
xmlResponseFields(MediaType.parseMediaType("application/vnd.com.example+xml"));
|
||||
@RenderedSnippetTest
|
||||
void customXmlResponseFields(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
xmlResponseFields(MediaType.parseMediaType("application/vnd.com.example+xml"), operationBuilder, snippets);
|
||||
}
|
||||
|
||||
private void xmlResponseFields(MediaType contentType) throws IOException {
|
||||
private void xmlResponseFields(MediaType contentType, OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one").type("b"),
|
||||
fieldWithPath("a/c").description("two").type("c"), fieldWithPath("a").description("three").type("a")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("<a><b>5</b><c>charlie</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, contentType.toString())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a/b`", "`b`", "one")
|
||||
.row("`a/c`", "`c`", "two")
|
||||
.row("`a`", "`a`", "three"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a/b`", "`b`", "one")
|
||||
.row("`a/c`", "`c`", "two")
|
||||
.row("`a`", "`a`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xmlAttribute() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void xmlAttribute(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type("b"),
|
||||
fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("<a id=\"1\">foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`b`", "one").row("`a/@id`", "`c`", "two"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a`", "`b`", "one")
|
||||
.row("`a/@id`", "`c`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalXmlAttribute() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalXmlAttribute(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type("b"),
|
||||
fieldWithPath("a/@id").description("two").type("c").optional()))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`b`", "one").row("`a/@id`", "`c`", "two"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a`", "`b`", "one")
|
||||
.row("`a/@id`", "`c`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAttributeDoesNotCauseFailure() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void undocumentedAttributeDoesNotCauseFailure(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type("a")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`a`", "one"));
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`a`", "`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
PayloadDocumentation
|
||||
.responseFields(fieldWithPath("id").description("one"), fieldWithPath("date").description("two"),
|
||||
fieldWithPath("assets").description("three"))
|
||||
.and(fieldWithPath("assets[]").description("four"), fieldWithPath("assets[].id").description("five"),
|
||||
fieldWithPath("assets[].name").description("six"))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"id\": 67,\"date\": \"2015-01-20\",\"assets\":" + " [{\"id\":356,\"name\": \"sample\"}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`id`", "`Number`", "one")
|
||||
.row("`date`", "`String`", "two")
|
||||
.row("`assets`", "`Array`", "three")
|
||||
.row("`assets[]`", "`Array`", "four")
|
||||
.row("`assets[].id`", "`Number`", "five")
|
||||
.row("`assets[].name`", "`String`", "six"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`id`", "`Number`", "one")
|
||||
.row("`date`", "`String`", "two")
|
||||
.row("`assets`", "`Array`", "three")
|
||||
.row("`assets[]`", "`Array`", "four")
|
||||
.row("`assets[].id`", "`Number`", "five")
|
||||
.row("`assets[].name`", "`String`", "six"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prefixedAdditionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void prefixedAdditionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
PayloadDocumentation.responseFields(fieldWithPath("a").description("one"))
|
||||
.andWithPrefix("a.", fieldWithPath("b").description("two"), fieldWithPath("c").description("three"))
|
||||
.document(this.operationBuilder.response().content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
.document(operationBuilder.response().content("{\"a\": {\"b\": 5, \"c\": \"charlie\"}}").build());
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a`", "`Object`", "one")
|
||||
.row("`a.b`", "`Number`", "two")
|
||||
.row("`a.c`", "`String`", "three"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithFieldsWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithFieldsWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("Foo|Bar").type("one|two").description("three|four")))
|
||||
.document(this.operationBuilder.response().content("{\"Foo|Bar\": 5}").build());
|
||||
assertThat(this.generatedSnippets.responseFields()).is(tableWithHeader("Path", "Type", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("`one|two`"), escapeIfNecessary("three|four")));
|
||||
.document(operationBuilder.response().content("{\"Foo|Bar\": 5}").build());
|
||||
assertThat(snippets.responseFields()).isTable(
|
||||
(table) -> table.withHeader("Path", "Type", "Description").row("`Foo|Bar`", "`one|two`", "three|four"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapResponseWithVaryingKeysMatchedUsingWildcard() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void mapResponseWithVaryingKeysMatchedUsingWildcard(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("things.*.size").description("one"),
|
||||
fieldWithPath("things.*.type").description("two")))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"things\": {\"12abf\": {\"type\":" + "\"Whale\", \"size\": \"HUGE\"},"
|
||||
+ "\"gzM33\" : {\"type\": \"Screw\"," + "\"size\": \"SMALL\"}}}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`things.*.size`", "`String`", "one")
|
||||
.row("`things.*.type`", "`String`", "two"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`things.*.size`", "`String`", "one")
|
||||
.row("`things.*.type`", "`String`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithArrayContainingFieldThatIsSometimesNull() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void responseWithArrayContainingFieldThatIsSometimesNull(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets) throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("assets[].name").description("one").type(JsonFieldType.STRING).optional()))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"assets\": [" + "{\"name\": \"sample1\"}, " + "{\"name\": null}, "
|
||||
+ "{\"name\": \"sample2\"}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`assets[].name`", "`String`", "one"));
|
||||
assertThat(snippets.responseFields()).isTable(
|
||||
(table) -> table.withHeader("Path", "Type", "Description").row("`assets[].name`", "`String`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionalFieldBeneathArrayThatIsSometimesAbsent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void optionalFieldBeneathArrayThatIsSometimesAbsent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER).optional(),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(this.operationBuilder.response()
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`a[].b`", "`Number`", "one")
|
||||
.row("`a[].c`", "`Number`", "two"));
|
||||
assertThat(snippets.responseFields()).isTable((table) -> table.withHeader("Path", "Type", "Description")
|
||||
.row("`a[].b`", "`Number`", "one")
|
||||
.row("`a[].c`", "`Number`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeDeterminationDoesNotSetTypeOnDescriptor() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void typeDeterminationDoesNotSetTypeOnDescriptor(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
FieldDescriptor descriptor = fieldWithPath("id").description("one");
|
||||
new ResponseFieldsSnippet(Arrays.asList(descriptor))
|
||||
.document(this.operationBuilder.response().content("{\"id\": 67}").build());
|
||||
.document(operationBuilder.response().content("{\"id\": 67}").build());
|
||||
assertThat(descriptor.getType()).isNull();
|
||||
assertThat(this.generatedSnippets.responseFields())
|
||||
.is(tableWithHeader("Path", "Type", "Description").row("`id`", "`Number`", "one"));
|
||||
assertThat(snippets.responseFields())
|
||||
.isTable((table) -> table.withHeader("Path", "Type", "Description").row("`id`", "`Number`", "one"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void attemptToDocumentFieldsWithNoResponseBody(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.build()))
|
||||
.withMessage("Cannot document response fields as the response body is empty");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void fieldWithExplicitTypeThatDoesNotMatchThePayload(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(operationBuilder.response().content("{ \"a\": 5 }}").build()))
|
||||
.withMessage("The documented type of the field 'a' is Object but the actual type is Number");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void fieldWithExplicitSpecificTypeThatActuallyVaries(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypesDoNotMatchException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("[].a").description("one").type(JsonFieldType.OBJECT)))
|
||||
.document(operationBuilder.response().content("[{ \"a\": 5 },{ \"a\": \"b\" }]").build()))
|
||||
.withMessage("The documented type of the field '[].a' is Object but the actual type is Varies");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedXmlResponseField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.response()
|
||||
.content("<a><b>5</b></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingXmlAttribute(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one").type("b"),
|
||||
fieldWithPath("a/@id").description("two").type("c")))
|
||||
.document(operationBuilder.response()
|
||||
.content("<a>foo</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/@id]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void documentedXmlAttributesAreRemoved(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(
|
||||
() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one").type("a")))
|
||||
.document(operationBuilder.response()
|
||||
.content("<a id=\"foo\">bar</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage(String.format("The following parts of the payload were not documented:%n<a>bar</a>%n"));
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void xmlResponseFieldWithNoType(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(FieldTypeRequiredException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.response()
|
||||
.content("<a>5</a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()));
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingXmlResponseField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a/b").description("one"), fieldWithPath("a").description("one")))
|
||||
.document(operationBuilder.response()
|
||||
.content("<a></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessage("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedXmlResponseFieldAndMissingXmlResponseField(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/b").description("one")))
|
||||
.document(operationBuilder.response()
|
||||
.content("<a><c>5</c></a>")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
|
||||
.build()))
|
||||
.withMessageStartingWith("The following parts of the payload were not documented:")
|
||||
.withMessageEndingWith("Fields with the following paths were not found in the payload: [a/b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void unsupportedContent(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(PayloadHandlingException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(Collections.<FieldDescriptor>emptyList())
|
||||
.document(operationBuilder.response()
|
||||
.content("Some plain text")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
|
||||
.build()))
|
||||
.withMessage("Cannot handle text/plain content as it could not be parsed as JSON or XML");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void nonOptionalFieldBeneathArrayThatIsSometimesNull(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"b\": null, \"c\": 2}," + " {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void nonOptionalFieldBeneathArrayThatIsSometimesAbsent(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new ResponseFieldsSnippet(
|
||||
Arrays.asList(fieldWithPath("a[].b").description("one").type(JsonFieldType.NUMBER),
|
||||
fieldWithPath("a[].c").description("two").type(JsonFieldType.NUMBER)))
|
||||
.document(operationBuilder.response()
|
||||
.content("{\"a\":[{\"b\": 1,\"c\": 2}, " + "{\"c\": 2}, {\"b\": 1,\"c\": 2}]}")
|
||||
.build()))
|
||||
.withMessageStartingWith("Fields with the following paths were not found in the payload: [a[].b]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link FormParametersSnippet} due to missing or
|
||||
* undocumented form parameters.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class FormParametersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build()))
|
||||
.withMessage("Form parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Form parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingParameters() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build()))
|
||||
.withMessage("Form parameters with the following names were not documented: [b]. Form parameters"
|
||||
+ " with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,17 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -40,147 +38,151 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class FormParametersSnippetTests extends AbstractSnippetTests {
|
||||
class FormParametersSnippetTests {
|
||||
|
||||
public FormParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void formParameters(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new FormParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParameterWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void formParameterWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredFormParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredFormParameter(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new FormParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedFormParametersCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedFormParametersCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalFormParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalFormParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost").content("b=bravo").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalFormParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalFormParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("form-parameters"))
|
||||
.willReturn(snippetResource("form-parameters-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "form-parameters", template = "form-parameters-with-title")
|
||||
void formParametersWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||
attributes(key("title").value("The title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.formParameters()).contains("The title");
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters()).contains("The title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParametersWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("form-parameters"))
|
||||
.willReturn(snippetResource("form-parameters-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "form-parameters", template = "form-parameters-with-extra-column")
|
||||
void formParametersWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters()).isTable((table) -> table.withHeader("Parameter", "Description", "Foo")
|
||||
.row("a", "one", "alpha")
|
||||
.row("b", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParametersWithOptionalColumn() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("form-parameters"))
|
||||
.willReturn(snippetResource("form-parameters-with-optional-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "form-parameters", template = "form-parameters-with-optional-column")
|
||||
void formParametersWithOptionalColumn(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.content("a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Optional", "Description").row("a", "true", "one")
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Optional", "Description")
|
||||
.row("a", "true", "one")
|
||||
.row("b", "false", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
RequestDocumentation.formParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptorsWithRelaxedFormParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptorsWithRelaxedFormParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
RequestDocumentation.relaxedFormParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.content("a=alpha&b=bravo&c=undocumented")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.formParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha&b=bravo&c=undocumented").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParametersWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void formParametersWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
RequestDocumentation.formParameters(parameterWithName("Foo|Bar").description("one|two"))
|
||||
.document(this.operationBuilder.request("http://localhost").content("Foo%7CBar=baz").build());
|
||||
assertThat(this.generatedSnippets.formParameters()).is(tableWithHeader("Parameter", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.request("http://localhost").content("Foo%7CBar=baz").build());
|
||||
assertThat(snippets.formParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost").content("a=alpha").build()))
|
||||
.withMessage("Form parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Form parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedAndMissingParameters(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new FormParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").content("b=bravo").build()))
|
||||
.withMessage("Form parameters with the following names were not documented: [b]. Form parameters"
|
||||
+ " with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.generate.RestDocumentationGenerator;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link PathParametersSnippet} due to missing or
|
||||
* undocumented path parameters.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PathParametersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedPathParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Collections.<ParameterDescriptor>emptyList()).document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPathParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingPathParameters() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{b}")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not documented: [b]. Path parameters with the"
|
||||
+ " following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,20 +18,20 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.generate.RestDocumentationGenerator;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -41,164 +41,192 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class PathParametersSnippetTests extends AbstractSnippetTests {
|
||||
class PathParametersSnippetTests {
|
||||
|
||||
public PathParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void pathParameters(OperationBuilder operationBuilder, AssertableSnippets snippets, TemplateFormat templateFormat)
|
||||
throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredPathParameter() throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedPathParametersCanBeIgnored() throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true).document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalPathParameter() throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one"),
|
||||
parameterWithName("b").description("two").optional()))
|
||||
.document(this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}")
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle("/{a}"), "Parameter", "Description").row("`a`", "one")
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalPathParameter() throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
||||
.document(this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}")
|
||||
@RenderedSnippetTest
|
||||
void ignoredPathParameter(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle("/{a}"), "Parameter", "Description").row("`a`", "one"));
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat), "Parameter", "Description")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithQueryString() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedPathParametersCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true).document(
|
||||
operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}").build());
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat), "Parameter", "Description")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalPathParameter(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one"),
|
||||
parameterWithName("b").description("two").optional()))
|
||||
.document(
|
||||
operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}").build());
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat, "/{a}"), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalPathParameter(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional())).document(
|
||||
operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}").build());
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat, "/{a}"), "Parameter", "Description")
|
||||
.row("`a`", "one"));
|
||||
}
|
||||
|
||||
@RenderedSnippetTest
|
||||
void pathParametersWithQueryString(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder
|
||||
.document(operationBuilder
|
||||
.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}?foo=bar")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithQueryStringWithParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void pathParametersWithQueryStringWithParameters(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder
|
||||
.document(operationBuilder
|
||||
.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}?foo={c}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
assertThat(snippets.pathParameters())
|
||||
.isTable((table) -> table.withTitleAndHeader(getTitle(templateFormat), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("path-parameters"))
|
||||
.willReturn(snippetResource("path-parameters-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "path-parameters", template = "path-parameters-with-title")
|
||||
void pathParametersWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||
attributes(key("title").value("The title")))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters()).contains("The title");
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(snippets.pathParameters()).contains("The title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("path-parameters"))
|
||||
.willReturn(snippetResource("path-parameters-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "path-parameters", template = "path-parameters-with-extra-column")
|
||||
void pathParametersWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
new PathParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(snippets.pathParameters()).isTable((table) -> table.withHeader("Parameter", "Description", "Foo")
|
||||
.row("a", "one", "alpha")
|
||||
.row("b", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
RequestDocumentation.pathParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle(), "Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}")
|
||||
.build());
|
||||
assertThat(snippets.pathParameters()).isTable(
|
||||
(table) -> table.withTitleAndHeader(getTitle(templateFormat, "/{a}/{b}"), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptorsWithRelaxedRequestParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptorsWithRelaxedRequestParameters(OperationBuilder operationBuilder,
|
||||
AssertableSnippets snippets, TemplateFormat templateFormat) throws IOException {
|
||||
RequestDocumentation.relaxedPathParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(this.operationBuilder
|
||||
.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}/{c}")
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/{b}/{c}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle("/{a}/{b}/{c}"), "Parameter", "Description").row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
assertThat(snippets.pathParameters()).isTable((table) -> table
|
||||
.withTitleAndHeader(getTitle(templateFormat, "/{a}/{b}/{c}"), "Parameter", "Description")
|
||||
.row("`a`", "one")
|
||||
.row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void pathParametersWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets,
|
||||
TemplateFormat templateFormat) throws IOException {
|
||||
RequestDocumentation.pathParameters(parameterWithName("Foo|Bar").description("one|two"))
|
||||
.document(
|
||||
this.operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "{Foo|Bar}")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.pathParameters())
|
||||
.is(tableWithTitleAndHeader(getTitle("{Foo|Bar}"), "Parameter", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "{Foo|Bar}")
|
||||
.build());
|
||||
assertThat(snippets.pathParameters()).isTable(
|
||||
(table) -> table.withTitleAndHeader(getTitle(templateFormat, "{Foo|Bar}"), "Parameter", "Description")
|
||||
.row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedPathParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{a}/")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
private String getTitle() {
|
||||
return getTitle("/{a}/{b}");
|
||||
@SnippetTest
|
||||
void missingPathParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
private String getTitle(String title) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.asciidoctor().getId())) {
|
||||
@SnippetTest
|
||||
void undocumentedAndMissingPathParameters(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.attribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/{b}")
|
||||
.build()))
|
||||
.withMessage("Path parameters with the following names were not documented: [b]. Path parameters with the"
|
||||
+ " following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
private String getTitle(TemplateFormat templateFormat) {
|
||||
return getTitle(templateFormat, "/{a}/{b}");
|
||||
}
|
||||
|
||||
private String getTitle(TemplateFormat templateFormat, String title) {
|
||||
if (templateFormat.getId().equals(TemplateFormats.asciidoctor().getId())) {
|
||||
return "+" + title + "+";
|
||||
}
|
||||
return "`" + title + "`";
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link QueryParametersSnippet} due to missing or
|
||||
* undocumented query parameters.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class QueryParametersSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha").build()))
|
||||
.withMessage("Query parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingParameter() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Query parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingParameters() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost?b=bravo").build()))
|
||||
.withMessage("Query parameters with the following names were not documented: [b]. Query parameters"
|
||||
+ " with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,17 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -40,142 +38,151 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class QueryParametersSnippetTests extends AbstractSnippetTests {
|
||||
class QueryParametersSnippetTests {
|
||||
|
||||
public QueryParametersSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void queryParameters(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new QueryParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one"), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterWithNoValue() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void queryParameterWithNoValue(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost?a").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||
.document(operationBuilder.request("http://localhost?a").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredQueryParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredQueryParameter(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new QueryParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").ignored(), parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedQueryParametersCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedQueryParametersCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(Arrays.asList(parameterWithName("b").description("two")), true)
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalQueryParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalQueryParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost?b=bravo").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalQueryParameter() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalQueryParameter(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional()))
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("query-parameters"))
|
||||
.willReturn(snippetResource("query-parameters-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "query-parameters", template = "query-parameters-with-title")
|
||||
void queryParametersWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||
attributes(key("title").value("The title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost?a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.queryParameters()).contains("The title");
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters()).contains("The title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("query-parameters"))
|
||||
.willReturn(snippetResource("query-parameters-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "query-parameters", template = "query-parameters-with-extra-column")
|
||||
void queryParametersWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(
|
||||
Arrays.asList(parameterWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
parameterWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost?a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters()).isTable((table) -> table.withHeader("Parameter", "Description", "Foo")
|
||||
.row("a", "one", "alpha")
|
||||
.row("b", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersWithOptionalColumn() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("query-parameters"))
|
||||
.willReturn(snippetResource("query-parameters-with-optional-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "query-parameters", template = "query-parameters-with-optional-column")
|
||||
void queryParametersWithOptionalColumn(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one").optional(),
|
||||
parameterWithName("b").description("two")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost?a=alpha&b=bravo")
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Optional", "Description").row("a", "true", "one")
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Optional", "Description")
|
||||
.row("a", "true", "one")
|
||||
.row("b", "false", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
RequestDocumentation.queryParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptorsWithRelaxedQueryParameters() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptorsWithRelaxedQueryParameters(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
RequestDocumentation.relaxedQueryParameters(parameterWithName("a").description("one"))
|
||||
.and(parameterWithName("b").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost?a=alpha&b=bravo&c=undocumented").build());
|
||||
assertThat(this.generatedSnippets.queryParameters())
|
||||
.is(tableWithHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost?a=alpha&b=bravo&c=undocumented").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void queryParametersWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
RequestDocumentation.queryParameters(parameterWithName("Foo|Bar").description("one|two"))
|
||||
.document(this.operationBuilder.request("http://localhost?Foo%7CBar=baz").build());
|
||||
assertThat(this.generatedSnippets.queryParameters()).is(tableWithHeader("Parameter", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.request("http://localhost?Foo%7CBar=baz").build());
|
||||
assertThat(snippets.queryParameters())
|
||||
.isTable((table) -> table.withHeader("Parameter", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Collections.<ParameterDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost?a=alpha").build()))
|
||||
.withMessage("Query parameters with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingParameter(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Query parameters with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedAndMissingParameters(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new QueryParametersSnippet(Arrays.asList(parameterWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost?b=bravo").build()))
|
||||
.withMessage("Query parameters with the following names were not documented: [b]. Query parameters"
|
||||
+ " with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.request;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||
|
||||
/**
|
||||
* Tests for failures when rendering {@link RequestPartsSnippet} due to missing or
|
||||
* undocumented request parts.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestPartsSnippetFailureTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void undocumentedPart() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Collections.<RequestPartDescriptor>emptyList())
|
||||
.document(this.operationBuilder.request("http://localhost").part("a", "alpha".getBytes()).build()))
|
||||
.withMessage("Request parts with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPart() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Arrays.asList(partWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Request parts with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undocumentedAndMissingParts() {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Arrays.asList(partWithName("a").description("one")))
|
||||
.document(this.operationBuilder.request("http://localhost").part("b", "bravo".getBytes()).build()))
|
||||
.withMessage("Request parts with the following names were not documented: [b]. Request parts with the"
|
||||
+ " following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,19 +18,17 @@ package org.springframework.restdocs.request;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.AbstractSnippetTests;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.snippet.SnippetException;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTemplate;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.SnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.partWithName;
|
||||
import static org.springframework.restdocs.snippet.Attributes.attributes;
|
||||
import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
@@ -40,145 +38,157 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RequestPartsSnippetTests extends AbstractSnippetTests {
|
||||
class RequestPartsSnippetTests {
|
||||
|
||||
public RequestPartsSnippetTests(String name, TemplateFormat templateFormat) {
|
||||
super(name, templateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestParts() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestParts(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestPartsSnippet(
|
||||
Arrays.asList(partWithName("a").description("one"), partWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "bravo".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts())
|
||||
.is(tableWithHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignoredRequestPart() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void ignoredRequestPart(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestPartsSnippet(Arrays.asList(partWithName("a").ignored(), partWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "bravo".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts()).is(tableWithHeader("Part", "Description").row("`b`", "two"));
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allUndocumentedRequestPartsCanBeIgnored() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void allUndocumentedRequestPartsCanBeIgnored(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartsSnippet(Arrays.asList(partWithName("b").description("two")), true)
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "bravo".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts()).is(tableWithHeader("Part", "Description").row("`b`", "two"));
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalRequestPart() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void missingOptionalRequestPart(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestPartsSnippet(
|
||||
Arrays.asList(partWithName("a").description("one").optional(), partWithName("b").description("two")))
|
||||
.document(this.operationBuilder.request("http://localhost").part("b", "bravo".getBytes()).build());
|
||||
assertThat(this.generatedSnippets.requestParts())
|
||||
.is(tableWithHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
.document(operationBuilder.request("http://localhost").part("b", "bravo".getBytes()).build());
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void presentOptionalRequestPart() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void presentOptionalRequestPart(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
new RequestPartsSnippet(Arrays.asList(partWithName("a").description("one").optional()))
|
||||
.document(this.operationBuilder.request("http://localhost").part("a", "one".getBytes()).build());
|
||||
assertThat(this.generatedSnippets.requestParts()).is(tableWithHeader("Part", "Description").row("`a`", "one"));
|
||||
.document(operationBuilder.request("http://localhost").part("a", "one".getBytes()).build());
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`a`", "one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsWithCustomAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-parts"))
|
||||
.willReturn(snippetResource("request-parts-with-title"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-parts", template = "request-parts-with-title")
|
||||
void requestPartsWithCustomAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartsSnippet(
|
||||
Arrays.asList(partWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
partWithName("b").description("two").attributes(key("foo").value("bravo"))),
|
||||
attributes(key("title").value("The title")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "alpha".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts()).contains("The title");
|
||||
assertThat(snippets.requestParts()).contains("The title");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsWithCustomDescriptorAttributes() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-parts"))
|
||||
.willReturn(snippetResource("request-parts-with-extra-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-parts", template = "request-parts-with-extra-column")
|
||||
void requestPartsWithCustomDescriptorAttributes(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartsSnippet(
|
||||
Arrays.asList(partWithName("a").description("one").attributes(key("foo").value("alpha")),
|
||||
partWithName("b").description("two").attributes(key("foo").value("bravo"))))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "alpha".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts())
|
||||
.is(tableWithHeader("Part", "Description", "Foo").row("a", "one", "alpha").row("b", "two", "bravo"));
|
||||
assertThat(snippets.requestParts()).isTable((table) -> table.withHeader("Part", "Description", "Foo")
|
||||
.row("a", "one", "alpha")
|
||||
.row("b", "two", "bravo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsWithOptionalColumn() throws IOException {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource("request-parts"))
|
||||
.willReturn(snippetResource("request-parts-with-optional-column"));
|
||||
@RenderedSnippetTest
|
||||
@SnippetTemplate(snippet = "request-parts", template = "request-parts-with-optional-column")
|
||||
void requestPartsWithOptionalColumn(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
new RequestPartsSnippet(
|
||||
Arrays.asList(partWithName("a").description("one").optional(), partWithName("b").description("two")))
|
||||
.document(this.operationBuilder
|
||||
.attribute(TemplateEngine.class.getName(), new MustacheTemplateEngine(resolver))
|
||||
.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "alpha".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts())
|
||||
.is(tableWithHeader("Part", "Optional", "Description").row("a", "true", "one").row("b", "false", "two"));
|
||||
assertThat(snippets.requestParts()).isTable((table) -> table.withHeader("Part", "Optional", "Description")
|
||||
.row("a", "true", "one")
|
||||
.row("b", "false", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalDescriptors() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void additionalDescriptors(OperationBuilder operationBuilder, AssertableSnippets snippets) throws IOException {
|
||||
RequestDocumentation.requestParts(partWithName("a").description("one"))
|
||||
.and(partWithName("b").description("two"))
|
||||
.document(this.operationBuilder.request("http://localhost")
|
||||
.document(operationBuilder.request("http://localhost")
|
||||
.part("a", "bravo".getBytes())
|
||||
.and()
|
||||
.part("b", "bravo".getBytes())
|
||||
.build());
|
||||
assertThat(this.generatedSnippets.requestParts())
|
||||
.is(tableWithHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`a`", "one").row("`b`", "two"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsWithEscapedContent() throws IOException {
|
||||
@RenderedSnippetTest
|
||||
void requestPartsWithEscapedContent(OperationBuilder operationBuilder, AssertableSnippets snippets)
|
||||
throws IOException {
|
||||
RequestDocumentation.requestParts(partWithName("Foo|Bar").description("one|two"))
|
||||
.document(this.operationBuilder.request("http://localhost").part("Foo|Bar", "baz".getBytes()).build());
|
||||
assertThat(this.generatedSnippets.requestParts()).is(tableWithHeader("Part", "Description")
|
||||
.row(escapeIfNecessary("`Foo|Bar`"), escapeIfNecessary("one|two")));
|
||||
.document(operationBuilder.request("http://localhost").part("Foo|Bar", "baz".getBytes()).build());
|
||||
assertThat(snippets.requestParts())
|
||||
.isTable((table) -> table.withHeader("Part", "Description").row("`Foo|Bar`", "one|two"));
|
||||
}
|
||||
|
||||
private String escapeIfNecessary(String input) {
|
||||
if (this.templateFormat.getId().equals(TemplateFormats.markdown().getId())) {
|
||||
return input;
|
||||
}
|
||||
return input.replace("|", "\\|");
|
||||
@SnippetTest
|
||||
void undocumentedPart(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Collections.<RequestPartDescriptor>emptyList())
|
||||
.document(operationBuilder.request("http://localhost").part("a", "alpha".getBytes()).build()))
|
||||
.withMessage("Request parts with the following names were not documented: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void missingPart(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Arrays.asList(partWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").build()))
|
||||
.withMessage("Request parts with the following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
@SnippetTest
|
||||
void undocumentedAndMissingParts(OperationBuilder operationBuilder) {
|
||||
assertThatExceptionOfType(SnippetException.class)
|
||||
.isThrownBy(() -> new RequestPartsSnippet(Arrays.asList(partWithName("a").description("one")))
|
||||
.document(operationBuilder.request("http://localhost").part("b", "bravo".getBytes()).build()))
|
||||
.withMessage("Request parts with the following names were not documented: [b]. Request parts with the"
|
||||
+ " following names were not found in the request: [a]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.restdocs.snippet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.ManualRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
@@ -30,82 +30,82 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class RestDocumentationContextPlaceholderResolverTests {
|
||||
class RestDocumentationContextPlaceholderResolverTests {
|
||||
|
||||
@Test
|
||||
public void kebabCaseMethodName() {
|
||||
void kebabCaseMethodName() {
|
||||
assertThat(createResolver("dashSeparatedMethodName").resolvePlaceholder("method-name"))
|
||||
.isEqualTo("dash-separated-method-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kebabCaseMethodNameWithUpperCaseOpeningSection() {
|
||||
void kebabCaseMethodNameWithUpperCaseOpeningSection() {
|
||||
assertThat(createResolver("URIDashSeparatedMethodName").resolvePlaceholder("method-name"))
|
||||
.isEqualTo("uri-dash-separated-method-name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kebabCaseMethodNameWithUpperCaseMidSection() {
|
||||
void kebabCaseMethodNameWithUpperCaseMidSection() {
|
||||
assertThat(createResolver("dashSeparatedMethodNameWithURIInIt").resolvePlaceholder("method-name"))
|
||||
.isEqualTo("dash-separated-method-name-with-uri-in-it");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kebabCaseMethodNameWithUpperCaseEndSection() {
|
||||
void kebabCaseMethodNameWithUpperCaseEndSection() {
|
||||
assertThat(createResolver("dashSeparatedMethodNameWithURI").resolvePlaceholder("method-name"))
|
||||
.isEqualTo("dash-separated-method-name-with-uri");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snakeCaseMethodName() {
|
||||
void snakeCaseMethodName() {
|
||||
assertThat(createResolver("underscoreSeparatedMethodName").resolvePlaceholder("method_name"))
|
||||
.isEqualTo("underscore_separated_method_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snakeCaseMethodNameWithUpperCaseOpeningSection() {
|
||||
void snakeCaseMethodNameWithUpperCaseOpeningSection() {
|
||||
assertThat(createResolver("URIUnderscoreSeparatedMethodName").resolvePlaceholder("method_name"))
|
||||
.isEqualTo("uri_underscore_separated_method_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snakeCaseMethodNameWithUpperCaseMidSection() {
|
||||
void snakeCaseMethodNameWithUpperCaseMidSection() {
|
||||
assertThat(createResolver("underscoreSeparatedMethodNameWithURIInIt").resolvePlaceholder("method_name"))
|
||||
.isEqualTo("underscore_separated_method_name_with_uri_in_it");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snakeCaseMethodNameWithUpperCaseEndSection() {
|
||||
void snakeCaseMethodNameWithUpperCaseEndSection() {
|
||||
assertThat(createResolver("underscoreSeparatedMethodNameWithURI").resolvePlaceholder("method_name"))
|
||||
.isEqualTo("underscore_separated_method_name_with_uri");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void camelCaseMethodName() {
|
||||
void camelCaseMethodName() {
|
||||
assertThat(createResolver("camelCaseMethodName").resolvePlaceholder("methodName"))
|
||||
.isEqualTo("camelCaseMethodName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kebabCaseClassName() {
|
||||
void kebabCaseClassName() {
|
||||
assertThat(createResolver().resolvePlaceholder("class-name"))
|
||||
.isEqualTo("rest-documentation-context-placeholder-resolver-tests");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snakeCaseClassName() {
|
||||
void snakeCaseClassName() {
|
||||
assertThat(createResolver().resolvePlaceholder("class_name"))
|
||||
.isEqualTo("rest_documentation_context_placeholder_resolver_tests");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void camelCaseClassName() {
|
||||
void camelCaseClassName() {
|
||||
assertThat(createResolver().resolvePlaceholder("ClassName"))
|
||||
.isEqualTo("RestDocumentationContextPlaceholderResolverTests");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stepCount() {
|
||||
void stepCount() {
|
||||
assertThat(createResolver("stepCount").resolvePlaceholder("step")).isEqualTo("1");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,9 +21,8 @@ import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.restdocs.ManualRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
@@ -40,10 +39,10 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class StandardWriterResolverTests {
|
||||
class StandardWriterResolverTests {
|
||||
|
||||
@Rule
|
||||
public final TemporaryFolder temp = new TemporaryFolder();
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private final PlaceholderResolverFactory placeholderResolverFactory = mock(PlaceholderResolverFactory.class);
|
||||
|
||||
@@ -51,21 +50,21 @@ public class StandardWriterResolverTests {
|
||||
TemplateFormats.asciidoctor());
|
||||
|
||||
@Test
|
||||
public void absoluteInput() {
|
||||
void absoluteInput() {
|
||||
String absolutePath = new File("foo").getAbsolutePath();
|
||||
assertThat(this.resolver.resolveFile(absolutePath, "bar.txt", createContext(absolutePath)))
|
||||
.isEqualTo(new File(absolutePath, "bar.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuredOutputAndRelativeInput() {
|
||||
void configuredOutputAndRelativeInput() {
|
||||
File outputDir = new File("foo").getAbsoluteFile();
|
||||
assertThat(this.resolver.resolveFile("bar", "baz.txt", createContext(outputDir.getAbsolutePath())))
|
||||
.isEqualTo(new File(outputDir, "bar/baz.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuredOutputAndAbsoluteInput() {
|
||||
void configuredOutputAndAbsoluteInput() {
|
||||
File outputDir = new File("foo").getAbsoluteFile();
|
||||
String absolutePath = new File("bar").getAbsolutePath();
|
||||
assertThat(this.resolver.resolveFile(absolutePath, "baz.txt", createContext(outputDir.getAbsolutePath())))
|
||||
@@ -73,8 +72,8 @@ public class StandardWriterResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholdersAreResolvedInOperationName() throws IOException {
|
||||
File outputDirectory = this.temp.newFolder();
|
||||
void placeholdersAreResolvedInOperationName() throws IOException {
|
||||
File outputDirectory = this.temp;
|
||||
RestDocumentationContext context = createContext(outputDirectory.getAbsolutePath());
|
||||
PlaceholderResolver resolver = mock(PlaceholderResolver.class);
|
||||
given(resolver.resolvePlaceholder("a")).willReturn("alpha");
|
||||
@@ -84,8 +83,8 @@ public class StandardWriterResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void placeholdersAreResolvedInSnippetName() throws IOException {
|
||||
File outputDirectory = this.temp.newFolder();
|
||||
void placeholdersAreResolvedInSnippetName() throws IOException {
|
||||
File outputDirectory = this.temp;
|
||||
RestDocumentationContext context = createContext(outputDirectory.getAbsolutePath());
|
||||
PlaceholderResolver resolver = mock(PlaceholderResolver.class);
|
||||
given(resolver.resolvePlaceholder("b")).willReturn("bravo");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2021 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,13 +21,12 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.GeneratedSnippets;
|
||||
import org.springframework.restdocs.testfixtures.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.AssertableSnippets;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.OperationBuilder;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -36,16 +35,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class TemplatedSnippetTests {
|
||||
|
||||
@Rule
|
||||
public OperationBuilder operationBuilder = new OperationBuilder(TemplateFormats.asciidoctor());
|
||||
|
||||
@Rule
|
||||
public GeneratedSnippets snippets = new GeneratedSnippets(TemplateFormats.asciidoctor());
|
||||
class TemplatedSnippetTests {
|
||||
|
||||
@Test
|
||||
public void attributesAreCopied() {
|
||||
void attributesAreCopied() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("a", "alpha");
|
||||
TemplatedSnippet snippet = new TestTemplatedSnippet(attributes);
|
||||
@@ -55,22 +48,23 @@ public class TemplatedSnippetTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullAttributesAreTolerated() {
|
||||
void nullAttributesAreTolerated() {
|
||||
assertThat(new TestTemplatedSnippet(null).getAttributes()).isNotNull();
|
||||
assertThat(new TestTemplatedSnippet(null).getAttributes()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snippetName() {
|
||||
void snippetName() {
|
||||
assertThat(new TestTemplatedSnippet(Collections.<String, Object>emptyMap()).getSnippetName()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleSnippetsCanBeProducedFromTheSameTemplate() throws IOException {
|
||||
new TestTemplatedSnippet("one", "multiple-snippets").document(this.operationBuilder.build());
|
||||
new TestTemplatedSnippet("two", "multiple-snippets").document(this.operationBuilder.build());
|
||||
assertThat(this.snippets.snippet("multiple-snippets-one")).isNotNull();
|
||||
assertThat(this.snippets.snippet("multiple-snippets-two")).isNotNull();
|
||||
@RenderedSnippetTest
|
||||
void multipleSnippetsCanBeProducedFromTheSameTemplate(OperationBuilder operationBuilder, AssertableSnippets snippet)
|
||||
throws IOException {
|
||||
new TestTemplatedSnippet("one", "multiple-snippets").document(operationBuilder.build());
|
||||
new TestTemplatedSnippet("two", "multiple-snippets").document(operationBuilder.build());
|
||||
assertThat(snippet.named("multiple-snippets-one")).exists();
|
||||
assertThat(snippet.named("multiple-snippets-two")).exists();
|
||||
}
|
||||
|
||||
private static class TestTemplatedSnippet extends TemplatedSnippet {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,7 +22,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
@@ -34,7 +34,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class StandardTemplateResourceResolverTests {
|
||||
class StandardTemplateResourceResolverTests {
|
||||
|
||||
private final TemplateResourceResolver resolver = new StandardTemplateResourceResolver(
|
||||
TemplateFormats.asciidoctor());
|
||||
@@ -42,7 +42,7 @@ public class StandardTemplateResourceResolverTests {
|
||||
private final TestClassLoader classLoader = new TestClassLoader();
|
||||
|
||||
@Test
|
||||
public void formatSpecificCustomSnippetHasHighestPrecedence() throws IOException {
|
||||
void formatSpecificCustomSnippetHasHighestPrecedence() throws IOException {
|
||||
this.classLoader.addResource("org/springframework/restdocs/templates/asciidoctor/test.snippet",
|
||||
getClass().getResource("test-format-specific-custom.snippet"));
|
||||
this.classLoader.addResource("org/springframework/restdocs/templates/test.snippet",
|
||||
@@ -62,7 +62,7 @@ public class StandardTemplateResourceResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generalCustomSnippetIsUsedInAbsenceOfFormatSpecificCustomSnippet() throws IOException {
|
||||
void generalCustomSnippetIsUsedInAbsenceOfFormatSpecificCustomSnippet() throws IOException {
|
||||
this.classLoader.addResource("org/springframework/restdocs/templates/test.snippet",
|
||||
getClass().getResource("test-custom.snippet"));
|
||||
this.classLoader.addResource("org/springframework/restdocs/templates/asciidoctor/default-test.snippet",
|
||||
@@ -80,7 +80,7 @@ public class StandardTemplateResourceResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultSnippetIsUsedInAbsenceOfCustomSnippets() throws Exception {
|
||||
void defaultSnippetIsUsedInAbsenceOfCustomSnippets() throws Exception {
|
||||
this.classLoader.addResource("org/springframework/restdocs/templates/asciidoctor/default-test.snippet",
|
||||
getClass().getResource("test-default.snippet"));
|
||||
Resource snippet = doWithThreadContextClassLoader(this.classLoader, new Callable<Resource>() {
|
||||
@@ -96,7 +96,7 @@ public class StandardTemplateResourceResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failsIfCustomAndDefaultSnippetsDoNotExist() {
|
||||
void failsIfCustomAndDefaultSnippetsDoNotExist() {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> doWithThreadContextClassLoader(this.classLoader,
|
||||
() -> StandardTemplateResourceResolverTests.this.resolver.resolveTemplateResource("test")))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.templates.mustache;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.restdocs.mustache.Template.Fragment;
|
||||
|
||||
@@ -32,10 +32,10 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class AsciidoctorTableCellContentLambdaTests {
|
||||
class AsciidoctorTableCellContentLambdaTests {
|
||||
|
||||
@Test
|
||||
public void verticalBarCharactersAreEscaped() throws IOException {
|
||||
void verticalBarCharactersAreEscaped() throws IOException {
|
||||
Fragment fragment = mock(Fragment.class);
|
||||
given(fragment.execute()).willReturn("|foo|bar|baz|");
|
||||
StringWriter writer = new StringWriter();
|
||||
@@ -44,7 +44,7 @@ public class AsciidoctorTableCellContentLambdaTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void escapedVerticalBarCharactersAreNotEscapedAgain() throws IOException {
|
||||
void escapedVerticalBarCharactersAreNotEscapedAgain() throws IOException {
|
||||
Fragment fragment = mock(Fragment.class);
|
||||
given(fragment.execute()).willReturn("\\|foo|bar\\|baz|");
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{title}}
|
||||
|
||||
Path | Type | Description
|
||||
---- | ---- | -----------
|
||||
{{#fields}}
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* The {@code GeneratedSnippets} rule is used to capture the snippets generated by a test
|
||||
* and assert their existence and content.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Andreas Evers
|
||||
*/
|
||||
public class GeneratedSnippets extends OperationTestRule {
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
private String operationName;
|
||||
|
||||
private File outputDirectory;
|
||||
|
||||
public GeneratedSnippets(TemplateFormat templateFormat) {
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, File outputDirectory, String operationName) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.operationName = operationName;
|
||||
return base;
|
||||
}
|
||||
|
||||
public String curlRequest() {
|
||||
return snippet("curl-request");
|
||||
}
|
||||
|
||||
public String httpieRequest() {
|
||||
return snippet("httpie-request");
|
||||
}
|
||||
|
||||
public String requestHeaders() {
|
||||
return snippet("request-headers");
|
||||
}
|
||||
|
||||
public String responseHeaders() {
|
||||
return snippet("response-headers");
|
||||
}
|
||||
|
||||
public String requestCookies() {
|
||||
return snippet("request-cookies");
|
||||
}
|
||||
|
||||
public String responseCookies() {
|
||||
return snippet("response-cookies");
|
||||
}
|
||||
|
||||
public String httpRequest() {
|
||||
return snippet("http-request");
|
||||
}
|
||||
|
||||
public String httpResponse() {
|
||||
return snippet("http-response");
|
||||
}
|
||||
|
||||
public String links() {
|
||||
return snippet("links");
|
||||
}
|
||||
|
||||
public String requestFields() {
|
||||
return snippet("request-fields");
|
||||
}
|
||||
|
||||
public String requestParts() {
|
||||
return snippet("request-parts");
|
||||
}
|
||||
|
||||
public String requestPartFields(String partName) {
|
||||
return snippet("request-part-" + partName + "-fields");
|
||||
}
|
||||
|
||||
public String responseFields() {
|
||||
return snippet("response-fields");
|
||||
}
|
||||
|
||||
public String pathParameters() {
|
||||
return snippet("path-parameters");
|
||||
}
|
||||
|
||||
public String queryParameters() {
|
||||
return snippet("query-parameters");
|
||||
}
|
||||
|
||||
public String formParameters() {
|
||||
return snippet("form-parameters");
|
||||
}
|
||||
|
||||
public String snippet(String name) {
|
||||
File snippetFile = getSnippetFile(name);
|
||||
try {
|
||||
return FileCopyUtils
|
||||
.copyToString(new InputStreamReader(new FileInputStream(snippetFile), StandardCharsets.UTF_8));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
fail("Failed to read '" + snippetFile + "'", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private File getSnippetFile(String name) {
|
||||
if (this.outputDirectory == null) {
|
||||
fail("Output directory was null");
|
||||
}
|
||||
if (this.operationName == null) {
|
||||
fail("Operation name was null");
|
||||
}
|
||||
File snippetDir = new File(this.outputDirectory, this.operationName);
|
||||
return new File(snippetDir, name + "." + this.templateFormat.getFileExtension());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
/**
|
||||
* Abstract base class for Operation-related {@link TestRule TestRules}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
abstract class OperationTestRule implements TestRule {
|
||||
|
||||
@Override
|
||||
public final Statement apply(Statement base, Description description) {
|
||||
return apply(base, determineOutputDirectory(description), determineOperationName(description));
|
||||
}
|
||||
|
||||
private File determineOutputDirectory(Description description) {
|
||||
return new File("build/" + description.getTestClass().getSimpleName());
|
||||
}
|
||||
|
||||
private String determineOperationName(Description description) {
|
||||
String operationName = description.getMethodName();
|
||||
int index = operationName.indexOf('[');
|
||||
if (index > 0) {
|
||||
operationName = operationName.substring(0, index);
|
||||
}
|
||||
return operationName;
|
||||
}
|
||||
|
||||
protected abstract Statement apply(Statement base, File outputDirectory, String operationName);
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
/**
|
||||
* JUnit {@code @Rule} to capture output from System.out and System.err.
|
||||
* <p>
|
||||
* To use add as a {@link Rule @Rule}:
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class MyTest {
|
||||
*
|
||||
* @Rule
|
||||
* public OutputCaptureRule output = new OutputCaptureRule();
|
||||
*
|
||||
* @Test
|
||||
* public void test() {
|
||||
* assertThat(output).contains("ok");
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class OutputCaptureRule implements TestRule, CapturedOutput {
|
||||
|
||||
private final OutputCapture delegate = new OutputCapture();
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, Description description) {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
OutputCaptureRule.this.delegate.push();
|
||||
try {
|
||||
base.evaluate();
|
||||
}
|
||||
finally {
|
||||
OutputCaptureRule.this.delegate.pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAll() {
|
||||
return this.delegate.getAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOut() {
|
||||
return this.delegate.getOut();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErr() {
|
||||
return this.delegate.getErr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,679 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.assertj.core.api.AbstractStringAssert;
|
||||
import org.assertj.core.api.AssertProvider;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* AssertJ {@link AssertProvider} for asserting that the generated snippets are correct.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class AssertableSnippets {
|
||||
|
||||
private final File outputDirectory;
|
||||
|
||||
private final String operationName;
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
AssertableSnippets(File outputDirectory, String operationName, TemplateFormat templateFormat) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.operationName = operationName;
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
public File named(String name) {
|
||||
return getSnippetFile(name);
|
||||
}
|
||||
|
||||
private File getSnippetFile(String name) {
|
||||
File snippetDir = new File(this.outputDirectory, this.operationName);
|
||||
return new File(snippetDir, name + "." + this.templateFormat.getFileExtension());
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider curlRequest() {
|
||||
return new CodeBlockSnippetAssertProvider("curl-request");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider formParameters() {
|
||||
return new TableSnippetAssertProvider("form-parameters");
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider httpieRequest() {
|
||||
return new CodeBlockSnippetAssertProvider("httpie-request");
|
||||
}
|
||||
|
||||
public HttpRequestSnippetAssertProvider httpRequest() {
|
||||
return new HttpRequestSnippetAssertProvider("http-request");
|
||||
}
|
||||
|
||||
public HttpResponseSnippetAssertProvider httpResponse() {
|
||||
return new HttpResponseSnippetAssertProvider("http-response");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider links() {
|
||||
return new TableSnippetAssertProvider("links");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider pathParameters() {
|
||||
return new TableSnippetAssertProvider("path-parameters");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider queryParameters() {
|
||||
return new TableSnippetAssertProvider("query-parameters");
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider requestBody() {
|
||||
return new CodeBlockSnippetAssertProvider("request-body");
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider requestBody(String suffix) {
|
||||
return new CodeBlockSnippetAssertProvider("request-body-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestCookies() {
|
||||
return new TableSnippetAssertProvider("request-cookies");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestCookies(String suffix) {
|
||||
return new TableSnippetAssertProvider("request-cookies-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestFields() {
|
||||
return new TableSnippetAssertProvider("request-fields");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestFields(String suffix) {
|
||||
return new TableSnippetAssertProvider("request-fields-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestHeaders() {
|
||||
return new TableSnippetAssertProvider("request-headers");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestHeaders(String suffix) {
|
||||
return new TableSnippetAssertProvider("request-headers-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider requestPartBody(String partName) {
|
||||
return new CodeBlockSnippetAssertProvider("request-part-%s-body".formatted(partName));
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider requestPartBody(String partName, String suffix) {
|
||||
return new CodeBlockSnippetAssertProvider("request-part-%s-body-%s".formatted(partName, suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestPartFields(String partName) {
|
||||
return new TableSnippetAssertProvider("request-part-%s-fields".formatted(partName));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestPartFields(String partName, String suffix) {
|
||||
return new TableSnippetAssertProvider("request-part-%s-fields-%s".formatted(partName, suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider requestParts() {
|
||||
return new TableSnippetAssertProvider("request-parts");
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider responseBody() {
|
||||
return new CodeBlockSnippetAssertProvider("response-body");
|
||||
}
|
||||
|
||||
public CodeBlockSnippetAssertProvider responseBody(String suffix) {
|
||||
return new CodeBlockSnippetAssertProvider("response-body-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider responseCookies() {
|
||||
return new TableSnippetAssertProvider("response-cookies");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider responseFields() {
|
||||
return new TableSnippetAssertProvider("response-fields");
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider responseFields(String suffix) {
|
||||
return new TableSnippetAssertProvider("response-fields-%s".formatted(suffix));
|
||||
}
|
||||
|
||||
public TableSnippetAssertProvider responseHeaders() {
|
||||
return new TableSnippetAssertProvider("response-headers");
|
||||
}
|
||||
|
||||
public final class TableSnippetAssertProvider implements AssertProvider<TableSnippetAssert> {
|
||||
|
||||
private final String snippetName;
|
||||
|
||||
private TableSnippetAssertProvider(String snippetName) {
|
||||
this.snippetName = snippetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableSnippetAssert assertThat() {
|
||||
try {
|
||||
String content = Files
|
||||
.readString(new File(AssertableSnippets.this.outputDirectory, AssertableSnippets.this.operationName
|
||||
+ "/" + this.snippetName + "." + AssertableSnippets.this.templateFormat.getFileExtension())
|
||||
.toPath());
|
||||
return new TableSnippetAssert(content);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class TableSnippetAssert extends AbstractStringAssert<TableSnippetAssert> {
|
||||
|
||||
private TableSnippetAssert(String actual) {
|
||||
super(actual, TableSnippetAssert.class);
|
||||
}
|
||||
|
||||
public void isTable(UnaryOperator<Table<?>> tableOperator) {
|
||||
Table<?> table = tableOperator
|
||||
.apply(AssertableSnippets.this.templateFormat.equals(TemplateFormats.asciidoctor())
|
||||
? new AsciidoctorTable() : new MarkdownTable());
|
||||
table.getLinesAsString();
|
||||
Assertions.assertThat(this.actual).isEqualTo(table.getLinesAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class Table<T extends Table<T>> extends SnippetContent {
|
||||
|
||||
public abstract T withHeader(String... columns);
|
||||
|
||||
public abstract T withTitleAndHeader(String title, String... columns);
|
||||
|
||||
public abstract T row(String... entries);
|
||||
|
||||
public abstract T configuration(String string);
|
||||
|
||||
}
|
||||
|
||||
private final class AsciidoctorTable extends Table<AsciidoctorTable> {
|
||||
|
||||
@Override
|
||||
public AsciidoctorTable withHeader(String... columns) {
|
||||
return withTitleAndHeader("", columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorTable withTitleAndHeader(String title, String... columns) {
|
||||
if (!title.isBlank()) {
|
||||
this.addLine("." + title);
|
||||
}
|
||||
this.addLine("|===");
|
||||
String header = "|" + StringUtils.collectionToDelimitedString(Arrays.asList(columns), "|");
|
||||
this.addLine(header);
|
||||
this.addLine("");
|
||||
this.addLine("|===");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorTable row(String... entries) {
|
||||
for (String entry : entries) {
|
||||
this.addLine(-1, "|" + escapeEntry(entry));
|
||||
}
|
||||
this.addLine(-1, "");
|
||||
return this;
|
||||
}
|
||||
|
||||
private String escapeEntry(String entry) {
|
||||
entry = entry.replace("|", "\\|");
|
||||
if (entry.startsWith("`") && entry.endsWith("`")) {
|
||||
return "`+" + entry.substring(1, entry.length() - 1) + "+`";
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorTable configuration(String configuration) {
|
||||
this.addLine(0, configuration);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class MarkdownTable extends Table<MarkdownTable> {
|
||||
|
||||
@Override
|
||||
public MarkdownTable withHeader(String... columns) {
|
||||
return withTitleAndHeader("", columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownTable withTitleAndHeader(String title, String... columns) {
|
||||
if (StringUtils.hasText(title)) {
|
||||
this.addLine(title);
|
||||
this.addLine("");
|
||||
}
|
||||
String header = StringUtils.collectionToDelimitedString(Arrays.asList(columns), " | ");
|
||||
this.addLine(header);
|
||||
List<String> components = new ArrayList<>();
|
||||
for (String column : columns) {
|
||||
StringBuilder dashes = new StringBuilder();
|
||||
for (int i = 0; i < column.length(); i++) {
|
||||
dashes.append("-");
|
||||
}
|
||||
components.add(dashes.toString());
|
||||
}
|
||||
this.addLine(StringUtils.collectionToDelimitedString(components, " | "));
|
||||
this.addLine("");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownTable row(String... entries) {
|
||||
this.addLine(-1, StringUtils.collectionToDelimitedString(Arrays.asList(entries), " | "));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownTable configuration(String configuration) {
|
||||
throw new UnsupportedOperationException("Markdown tables do not support configuration");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class CodeBlockSnippetAssertProvider implements AssertProvider<CodeBlockSnippetAssert> {
|
||||
|
||||
private final String snippetName;
|
||||
|
||||
private CodeBlockSnippetAssertProvider(String snippetName) {
|
||||
this.snippetName = snippetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodeBlockSnippetAssert assertThat() {
|
||||
try {
|
||||
String content = Files
|
||||
.readString(new File(AssertableSnippets.this.outputDirectory, AssertableSnippets.this.operationName
|
||||
+ "/" + this.snippetName + "." + AssertableSnippets.this.templateFormat.getFileExtension())
|
||||
.toPath());
|
||||
return new CodeBlockSnippetAssert(content);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class CodeBlockSnippetAssert extends AbstractStringAssert<CodeBlockSnippetAssert> {
|
||||
|
||||
private CodeBlockSnippetAssert(String actual) {
|
||||
super(actual, CodeBlockSnippetAssert.class);
|
||||
}
|
||||
|
||||
public void isCodeBlock(UnaryOperator<CodeBlock<?>> codeBlockOperator) {
|
||||
CodeBlock<?> codeBlock = codeBlockOperator
|
||||
.apply(AssertableSnippets.this.templateFormat.equals(TemplateFormats.asciidoctor())
|
||||
? new AsciidoctorCodeBlock() : new MarkdownCodeBlock());
|
||||
Assertions.assertThat(this.actual).isEqualTo(codeBlock.getLinesAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class CodeBlock<T extends CodeBlock<T>> extends SnippetContent {
|
||||
|
||||
public abstract T withLanguage(String language);
|
||||
|
||||
public abstract T withOptions(String options);
|
||||
|
||||
public abstract T withLanguageAndOptions(String language, String options);
|
||||
|
||||
public abstract T content(String string);
|
||||
|
||||
}
|
||||
|
||||
private final class AsciidoctorCodeBlock extends CodeBlock<AsciidoctorCodeBlock> {
|
||||
|
||||
@Override
|
||||
public AsciidoctorCodeBlock withLanguage(String language) {
|
||||
addLine("[source,%s]".formatted(language));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorCodeBlock withOptions(String options) {
|
||||
addLine("[source,options=\"%s\"]".formatted(options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorCodeBlock withLanguageAndOptions(String language, String options) {
|
||||
addLine("[source,%s,options=\"%s\"]".formatted(language, options));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorCodeBlock content(String content) {
|
||||
addLine("----");
|
||||
addLine(content);
|
||||
addLine("----");
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class MarkdownCodeBlock extends CodeBlock<MarkdownCodeBlock> {
|
||||
|
||||
@Override
|
||||
public MarkdownCodeBlock withLanguage(String language) {
|
||||
addLine("```%s".formatted(language));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownCodeBlock withOptions(String options) {
|
||||
addLine("```");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownCodeBlock withLanguageAndOptions(String language, String options) {
|
||||
addLine("```%s".formatted(language));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownCodeBlock content(String content) {
|
||||
addLine(content);
|
||||
addLine("```");
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class HttpRequestSnippetAssertProvider implements AssertProvider<HttpRequestSnippetAssert> {
|
||||
|
||||
private final String snippetName;
|
||||
|
||||
private HttpRequestSnippetAssertProvider(String snippetName) {
|
||||
this.snippetName = snippetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequestSnippetAssert assertThat() {
|
||||
try {
|
||||
String content = Files
|
||||
.readString(new File(AssertableSnippets.this.outputDirectory, AssertableSnippets.this.operationName
|
||||
+ "/" + this.snippetName + "." + AssertableSnippets.this.templateFormat.getFileExtension())
|
||||
.toPath());
|
||||
return new HttpRequestSnippetAssert(content);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class HttpRequestSnippetAssert extends AbstractStringAssert<HttpRequestSnippetAssert> {
|
||||
|
||||
private HttpRequestSnippetAssert(String actual) {
|
||||
super(actual, HttpRequestSnippetAssert.class);
|
||||
}
|
||||
|
||||
public void isHttpRequest(UnaryOperator<HttpRequest<?>> operator) {
|
||||
HttpRequest<?> codeBlock = operator
|
||||
.apply(AssertableSnippets.this.templateFormat.equals(TemplateFormats.asciidoctor())
|
||||
? new AsciidoctorHttpRequest() : new MarkdownHttpRequest());
|
||||
Assertions.assertThat(this.actual).isEqualTo(codeBlock.getLinesAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class HttpRequest<T extends HttpRequest<T>> extends SnippetContent {
|
||||
|
||||
public T get(String uri) {
|
||||
return request("GET", uri);
|
||||
}
|
||||
|
||||
public T post(String uri) {
|
||||
return request("POST", uri);
|
||||
}
|
||||
|
||||
public T put(String uri) {
|
||||
return request("PUT", uri);
|
||||
}
|
||||
|
||||
public T patch(String uri) {
|
||||
return request("PATCH", uri);
|
||||
}
|
||||
|
||||
public T delete(String uri) {
|
||||
return request("DELETE", uri);
|
||||
}
|
||||
|
||||
protected abstract T request(String method, String uri);
|
||||
|
||||
public abstract T header(String name, Object value);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T content(String content) {
|
||||
addLine(-1, content);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class AsciidoctorHttpRequest extends HttpRequest<AsciidoctorHttpRequest> {
|
||||
|
||||
private int headerOffset = 3;
|
||||
|
||||
@Override
|
||||
protected AsciidoctorHttpRequest request(String method, String uri) {
|
||||
addLine("[source,http,options=\"nowrap\"]");
|
||||
addLine("----");
|
||||
addLine("%s %s HTTP/1.1".formatted(method, uri));
|
||||
addLine("");
|
||||
addLine("----");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorHttpRequest header(String name, Object value) {
|
||||
addLine(this.headerOffset++, "%s: %s".formatted(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class MarkdownHttpRequest extends HttpRequest<MarkdownHttpRequest> {
|
||||
|
||||
private int headerOffset = 2;
|
||||
|
||||
@Override
|
||||
public MarkdownHttpRequest request(String method, String uri) {
|
||||
addLine("```http");
|
||||
addLine("%s %s HTTP/1.1".formatted(method, uri));
|
||||
addLine("");
|
||||
addLine("```");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownHttpRequest header(String name, Object value) {
|
||||
addLine(this.headerOffset++, "%s: %s".formatted(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class HttpResponseSnippetAssertProvider implements AssertProvider<HttpResponseSnippetAssert> {
|
||||
|
||||
private final String snippetName;
|
||||
|
||||
private HttpResponseSnippetAssertProvider(String snippetName) {
|
||||
this.snippetName = snippetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponseSnippetAssert assertThat() {
|
||||
try {
|
||||
String content = Files
|
||||
.readString(new File(AssertableSnippets.this.outputDirectory, AssertableSnippets.this.operationName
|
||||
+ "/" + this.snippetName + "." + AssertableSnippets.this.templateFormat.getFileExtension())
|
||||
.toPath());
|
||||
return new HttpResponseSnippetAssert(content);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final class HttpResponseSnippetAssert extends AbstractStringAssert<HttpResponseSnippetAssert> {
|
||||
|
||||
private HttpResponseSnippetAssert(String actual) {
|
||||
super(actual, HttpResponseSnippetAssert.class);
|
||||
}
|
||||
|
||||
public void isHttpResponse(UnaryOperator<HttpResponse<?>> operator) {
|
||||
HttpResponse<?> httpResponse = operator
|
||||
.apply(AssertableSnippets.this.templateFormat.equals(TemplateFormats.asciidoctor())
|
||||
? new AsciidoctorHttpResponse() : new MarkdownHttpResponse());
|
||||
Assertions.assertThat(this.actual).isEqualTo(httpResponse.getLinesAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public abstract class HttpResponse<T extends HttpResponse<T>> extends SnippetContent {
|
||||
|
||||
public T ok() {
|
||||
return status("200 OK");
|
||||
}
|
||||
|
||||
public T badRequest() {
|
||||
return status("400 Bad Request");
|
||||
}
|
||||
|
||||
public T status(int status) {
|
||||
return status("%d ".formatted(status));
|
||||
}
|
||||
|
||||
protected abstract T status(String status);
|
||||
|
||||
public abstract T header(String name, Object value);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T content(String content) {
|
||||
addLine(-1, content);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class AsciidoctorHttpResponse extends HttpResponse<AsciidoctorHttpResponse> {
|
||||
|
||||
private int headerOffset = 3;
|
||||
|
||||
@Override
|
||||
protected AsciidoctorHttpResponse status(String status) {
|
||||
addLine("[source,http,options=\"nowrap\"]");
|
||||
addLine("----");
|
||||
addLine("HTTP/1.1 %s".formatted(status));
|
||||
addLine("");
|
||||
addLine("----");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsciidoctorHttpResponse header(String name, Object value) {
|
||||
addLine(this.headerOffset++, "%s: %s".formatted(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final class MarkdownHttpResponse extends HttpResponse<MarkdownHttpResponse> {
|
||||
|
||||
private int headerOffset = 2;
|
||||
|
||||
@Override
|
||||
public MarkdownHttpResponse status(String status) {
|
||||
addLine("```http");
|
||||
addLine("HTTP/1.1 %s".formatted(status));
|
||||
addLine("");
|
||||
addLine("```");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarkdownHttpResponse header(String name, Object value) {
|
||||
addLine(this.headerOffset++, "%s: %s".formatted(name, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SnippetContent {
|
||||
|
||||
private List<String> lines = new ArrayList<>();
|
||||
|
||||
protected void addLine(String line) {
|
||||
this.lines.add(line);
|
||||
}
|
||||
|
||||
protected void addLine(int index, String line) {
|
||||
this.lines.add(determineIndex(index), line);
|
||||
}
|
||||
|
||||
private int determineIndex(int index) {
|
||||
if (index >= 0) {
|
||||
return index;
|
||||
}
|
||||
return index + this.lines.size();
|
||||
}
|
||||
|
||||
protected String getLinesAsString() {
|
||||
StringWriter writer = new StringWriter();
|
||||
Iterator<String> iterator = this.lines.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
writer.append(String.format("%s", iterator.next()));
|
||||
if (iterator.hasNext()) {
|
||||
writer.append(String.format("%n"));
|
||||
}
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,16 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
/**
|
||||
* Provides access to {@link System#out System.out} and {@link System#err System.err}
|
||||
* output that has been captured by the {@link OutputCaptureRule}. Can be used to apply
|
||||
* assertions using AssertJ. For example: <pre class="code">
|
||||
* assertThat(output).contains("started"); // Checks all output
|
||||
* assertThat(output.getErr()).contains("failed"); // Only checks System.err
|
||||
* assertThat(output.getOut()).contains("ok"); // Only checks System.out
|
||||
* </pre>
|
||||
* output that has been captured.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
@@ -26,8 +26,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -59,21 +57,27 @@ import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class OperationBuilder extends OperationTestRule {
|
||||
public class OperationBuilder {
|
||||
|
||||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
|
||||
private OperationResponseBuilder responseBuilder;
|
||||
private final File outputDirectory;
|
||||
|
||||
private String name;
|
||||
|
||||
private File outputDirectory;
|
||||
private final String name;
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
private OperationResponseBuilder responseBuilder;
|
||||
|
||||
private OperationRequestBuilder requestBuilder;
|
||||
|
||||
public OperationBuilder(TemplateFormat templateFormat) {
|
||||
OperationBuilder(File outputDirectory, String name) {
|
||||
this(outputDirectory, name, null);
|
||||
}
|
||||
|
||||
OperationBuilder(File outputDirectory, String name, TemplateFormat templateFormat) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.name = name;
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
@@ -92,13 +96,6 @@ public class OperationBuilder extends OperationTestRule {
|
||||
return this;
|
||||
}
|
||||
|
||||
private void prepare(String operationName, File outputDirectory) {
|
||||
this.name = operationName;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.requestBuilder = null;
|
||||
this.attributes.clear();
|
||||
}
|
||||
|
||||
public Operation build() {
|
||||
if (this.attributes.get(TemplateEngine.class.getName()) == null) {
|
||||
Map<String, Object> templateContext = new HashMap<>();
|
||||
@@ -127,12 +124,6 @@ public class OperationBuilder extends OperationTestRule {
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement apply(Statement base, File outputDirectory, String operationName) {
|
||||
prepare(operationName, outputDirectory);
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic builder API for creating an {@link OperationRequest}.
|
||||
*/
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures;
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -35,8 +35,6 @@ import org.springframework.util.Assert;
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Sam Brannen
|
||||
* @see OutputCaptureRule
|
||||
*/
|
||||
class OutputCapture implements CapturedOutput {
|
||||
|
||||
@@ -61,7 +59,7 @@ class OutputCapture implements CapturedOutput {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof CapturedOutput || obj instanceof CharSequence) {
|
||||
if (obj instanceof CharSequence) {
|
||||
return getAll().equals(obj.toString());
|
||||
}
|
||||
return false;
|
||||
@@ -123,17 +121,17 @@ class OutputCapture implements CapturedOutput {
|
||||
}
|
||||
|
||||
/**
|
||||
* A capture session that captures {@link System#out System.out} and {@link System#out
|
||||
* A capture session that captures {@link System#out System.out} and {@link System#err
|
||||
* System.err}.
|
||||
*/
|
||||
private static class SystemCapture {
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final PrintStreamCapture out;
|
||||
|
||||
private final PrintStreamCapture err;
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final List<CapturedString> capturedStrings = new ArrayList<>();
|
||||
|
||||
SystemCapture() {
|
||||
@@ -195,8 +193,8 @@ class OutputCapture implements CapturedOutput {
|
||||
}
|
||||
|
||||
private static PrintStream getSystemStream(PrintStream printStream) {
|
||||
while (printStream instanceof PrintStreamCapture) {
|
||||
printStream = ((PrintStreamCapture) printStream).getParent();
|
||||
while (printStream instanceof PrintStreamCapture printStreamCapture) {
|
||||
printStream = printStreamCapture.getParent();
|
||||
}
|
||||
return printStream;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
||||
import org.junit.jupiter.api.extension.ParameterContext;
|
||||
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
||||
import org.junit.jupiter.api.extension.ParameterResolver;
|
||||
|
||||
/**
|
||||
* JUnit Jupiter {@code @Extension} to capture {@link System#out System.out} and
|
||||
* {@link System#err System.err}. Can be registered for an entire test class or for an
|
||||
* individual test method through {@link ExtendWith @ExtendWith}. This extension provides
|
||||
* {@linkplain ParameterResolver parameter resolution} for a {@link CapturedOutput}
|
||||
* instance which can be used to assert that the correct output was written.
|
||||
* <p>
|
||||
* To use with {@link ExtendWith @ExtendWith}, inject the {@link CapturedOutput} as an
|
||||
* argument to your test class constructor, test method, or lifecycle methods:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @ExtendWith(OutputCaptureExtension.class)
|
||||
* class MyTest {
|
||||
*
|
||||
* @Test
|
||||
* void test(CapturedOutput output) {
|
||||
* System.out.println("ok");
|
||||
* assertThat(output).contains("ok");
|
||||
* System.err.println("error");
|
||||
* }
|
||||
*
|
||||
* @AfterEach
|
||||
* void after(CapturedOutput output) {
|
||||
* assertThat(output.getOut()).contains("ok");
|
||||
* assertThat(output.getErr()).contains("error");
|
||||
* }
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Sam Brannen
|
||||
* @see CapturedOutput
|
||||
*/
|
||||
public class OutputCaptureExtension
|
||||
implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
|
||||
|
||||
OutputCaptureExtension() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) throws Exception {
|
||||
getOutputCapture(context).push();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) throws Exception {
|
||||
getOutputCapture(context).pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) throws Exception {
|
||||
getOutputCapture(context).push();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) throws Exception {
|
||||
getOutputCapture(context).pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
||||
throws ParameterResolutionException {
|
||||
return CapturedOutput.class.equals(parameterContext.getParameter().getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
|
||||
return getOutputCapture(extensionContext);
|
||||
}
|
||||
|
||||
private OutputCapture getOutputCapture(ExtensionContext context) {
|
||||
return getStore(context).getOrComputeIfAbsent(OutputCapture.class);
|
||||
}
|
||||
|
||||
private Store getStore(ExtensionContext context) {
|
||||
return context.getStore(Namespace.create(getClass()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.TestTemplate;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
|
||||
/**
|
||||
* Signals that a method is a template for a test that renders a snippet. The test will be
|
||||
* executed once for each of the two supported snippet formats (Asciidoctor and Markdown).
|
||||
* <p>
|
||||
* A rendered snippet test method can inject the following types:
|
||||
* <ul>
|
||||
* <li>{@link OperationBuilder}</li>
|
||||
* <li>{@link AssertableSnippets}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@TestTemplate
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExtendWith(RenderedSnippetTestExtension.class)
|
||||
public @interface RenderedSnippetTest {
|
||||
|
||||
/**
|
||||
* The snippet formats to render.
|
||||
* @return the formats
|
||||
*/
|
||||
Format[] format() default { Format.ASCIIDOCTOR, Format.MARKDOWN };
|
||||
|
||||
enum Format {
|
||||
|
||||
/**
|
||||
* Asciidoctor snippet format.
|
||||
*/
|
||||
ASCIIDOCTOR(TemplateFormats.asciidoctor()),
|
||||
|
||||
/**
|
||||
* Markdown snippet format.
|
||||
*/
|
||||
MARKDOWN(TemplateFormats.markdown());
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
Format(TemplateFormat templateFormat) {
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
TemplateFormat templateFormat() {
|
||||
return this.templateFormat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.extension.Extension;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
||||
import org.junit.jupiter.api.extension.ParameterContext;
|
||||
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
||||
import org.junit.jupiter.api.extension.ParameterResolver;
|
||||
import org.junit.jupiter.api.extension.TestTemplateInvocationContext;
|
||||
import org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider;
|
||||
import org.junit.platform.commons.util.AnnotationUtils;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateResourceResolver;
|
||||
import org.springframework.restdocs.templates.mustache.MustacheTemplateEngine;
|
||||
import org.springframework.restdocs.testfixtures.jupiter.RenderedSnippetTest.Format;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* {@link TestTemplateInvocationContextProvider} for
|
||||
* {@link RenderedSnippetTest @RenderedSnippetTest} and
|
||||
* {@link SnippetTemplate @SnippetTemplate}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class RenderedSnippetTestExtension implements TestTemplateInvocationContextProvider {
|
||||
|
||||
@Override
|
||||
public boolean supportsTestTemplate(ExtensionContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
|
||||
return AnnotationUtils.findAnnotation(context.getRequiredTestMethod(), RenderedSnippetTest.class)
|
||||
.map((renderedSnippetTest) -> Stream.of(renderedSnippetTest.format())
|
||||
.map(Format::templateFormat)
|
||||
.map(SnippetTestInvocationContext::new)
|
||||
.map(TestTemplateInvocationContext.class::cast))
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
static class SnippetTestInvocationContext implements TestTemplateInvocationContext {
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
SnippetTestInvocationContext(TemplateFormat templateFormat) {
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Extension> getAdditionalExtensions() {
|
||||
return List.of(new RenderedSnippetTestParameterResolver(this.templateFormat));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(int invocationIndex) {
|
||||
return this.templateFormat.getId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class RenderedSnippetTestParameterResolver implements ParameterResolver {
|
||||
|
||||
private final TemplateFormat templateFormat;
|
||||
|
||||
RenderedSnippetTestParameterResolver(TemplateFormat templateFormat) {
|
||||
this.templateFormat = templateFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
||||
throws ParameterResolutionException {
|
||||
Class<?> parameterType = parameterContext.getParameter().getType();
|
||||
return AssertableSnippets.class.equals(parameterType) || OperationBuilder.class.equals(parameterType)
|
||||
|| TemplateFormat.class.equals(parameterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
|
||||
Class<?> parameterType = parameterContext.getParameter().getType();
|
||||
if (AssertableSnippets.class.equals(parameterType)) {
|
||||
return getStore(extensionContext).getOrComputeIfAbsent(AssertableSnippets.class,
|
||||
(key) -> new AssertableSnippets(determineOutputDirectory(extensionContext),
|
||||
determineOperationName(extensionContext), this.templateFormat));
|
||||
}
|
||||
if (TemplateFormat.class.equals(parameterType)) {
|
||||
return this.templateFormat;
|
||||
}
|
||||
return getStore(extensionContext).getOrComputeIfAbsent(OperationBuilder.class, (key) -> {
|
||||
OperationBuilder operationBuilder = new OperationBuilder(determineOutputDirectory(extensionContext),
|
||||
determineOperationName(extensionContext), this.templateFormat);
|
||||
AnnotationUtils.findAnnotation(extensionContext.getRequiredTestMethod(), SnippetTemplate.class)
|
||||
.ifPresent((snippetTemplate) -> {
|
||||
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);
|
||||
given(resolver.resolveTemplateResource(snippetTemplate.snippet()))
|
||||
.willReturn(snippetResource(snippetTemplate.template(), this.templateFormat));
|
||||
operationBuilder.attribute(TemplateEngine.class.getName(),
|
||||
new MustacheTemplateEngine(resolver));
|
||||
});
|
||||
|
||||
return operationBuilder;
|
||||
});
|
||||
}
|
||||
|
||||
private Store getStore(ExtensionContext extensionContext) {
|
||||
return extensionContext.getStore(Namespace.create(getClass()));
|
||||
}
|
||||
|
||||
private File determineOutputDirectory(ExtensionContext extensionContext) {
|
||||
return new File("build/" + extensionContext.getRequiredTestClass().getSimpleName());
|
||||
}
|
||||
|
||||
private String determineOperationName(ExtensionContext extensionContext) {
|
||||
String operationName = extensionContext.getRequiredTestMethod().getName();
|
||||
int index = operationName.indexOf('[');
|
||||
if (index > 0) {
|
||||
operationName = operationName.substring(0, index);
|
||||
}
|
||||
return operationName;
|
||||
}
|
||||
|
||||
private FileSystemResource snippetResource(String name, TemplateFormat templateFormat) {
|
||||
return new FileSystemResource(
|
||||
"src/test/resources/custom-snippet-templates/" + templateFormat.getId() + "/" + name + ".snippet");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Customizes the template that will be used when rendering a snippet in a
|
||||
* {@link RenderedSnippetTest rendered snippet test}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface SnippetTemplate {
|
||||
|
||||
/**
|
||||
* The name of the snippet whose template should be customized.
|
||||
* @return the snippet name
|
||||
*/
|
||||
String snippet();
|
||||
|
||||
/**
|
||||
* The custom template to use when rendering the snippet.
|
||||
* @return the custom template
|
||||
*/
|
||||
String template();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
|
||||
/**
|
||||
* Signals that a method is a test of a {@link Snippet}. Typically used to test scenarios
|
||||
* where a failure occurs before the snippet is rendered. To test snippet rendering, use
|
||||
* {@link RenderedSnippetTest}.
|
||||
* <p>
|
||||
* A snippet test method can inject the following types:
|
||||
* <ul>
|
||||
* <li>{@link OperationBuilder}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Test
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExtendWith(SnippetTestExtension.class)
|
||||
public @interface SnippetTest {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.restdocs.testfixtures.jupiter;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
||||
import org.junit.jupiter.api.extension.ParameterContext;
|
||||
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
||||
import org.junit.jupiter.api.extension.ParameterResolver;
|
||||
|
||||
/**
|
||||
* {@link ParameterResolver} for {@link SnippetTest @SnippetTest}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class SnippetTestExtension implements ParameterResolver {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
||||
throws ParameterResolutionException {
|
||||
Class<?> parameterType = parameterContext.getParameter().getType();
|
||||
return OperationBuilder.class.equals(parameterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
|
||||
return getStore(extensionContext).getOrComputeIfAbsent(OperationBuilder.class,
|
||||
(key) -> new OperationBuilder(determineOutputDirectory(extensionContext),
|
||||
determineOperationName(extensionContext)));
|
||||
}
|
||||
|
||||
private Store getStore(ExtensionContext extensionContext) {
|
||||
return extensionContext.getStore(Namespace.create(getClass()));
|
||||
}
|
||||
|
||||
private File determineOutputDirectory(ExtensionContext extensionContext) {
|
||||
return new File("build/" + extensionContext.getRequiredTestClass().getSimpleName());
|
||||
}
|
||||
|
||||
private String determineOperationName(ExtensionContext extensionContext) {
|
||||
String operationName = extensionContext.getRequiredTestMethod().getName();
|
||||
int index = operationName.indexOf('[');
|
||||
if (index > 0) {
|
||||
operationName = operationName.substring(0, index);
|
||||
}
|
||||
return operationName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,8 +16,8 @@ dependencies {
|
||||
internal(platform(project(":spring-restdocs-platform")))
|
||||
|
||||
testImplementation(testFixtures(project(":spring-restdocs-core")))
|
||||
testImplementation("junit:junit")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.hamcrest:hamcrest-library")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
import jakarta.servlet.http.Part;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -46,19 +46,19 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class MockMvcRequestConverterTests {
|
||||
class MockMvcRequestConverterTests {
|
||||
|
||||
private final MockMvcRequestConverter factory = new MockMvcRequestConverter();
|
||||
|
||||
@Test
|
||||
public void httpRequest() {
|
||||
void httpRequest() {
|
||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.get("/foo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpRequestWithCustomPort() {
|
||||
void httpRequestWithCustomPort() {
|
||||
MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());
|
||||
mockRequest.setServerPort(8080);
|
||||
OperationRequest request = this.factory.convert(mockRequest);
|
||||
@@ -67,14 +67,14 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithContextPath() {
|
||||
void requestWithContextPath() {
|
||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.get("/foo/bar").contextPath("/foo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo/bar"));
|
||||
assertThat(request.getMethod()).isEqualTo(HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithHeaders() {
|
||||
void requestWithHeaders() {
|
||||
OperationRequest request = createOperationRequest(
|
||||
MockMvcRequestBuilders.get("/foo").header("a", "alpha", "apple").header("b", "bravo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
@@ -84,7 +84,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithCookies() {
|
||||
void requestWithCookies() {
|
||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.get("/foo")
|
||||
.cookie(new jakarta.servlet.http.Cookie("cookieName1", "cookieVal1"),
|
||||
new jakarta.servlet.http.Cookie("cookieName2", "cookieVal2")));
|
||||
@@ -104,7 +104,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpsRequest() {
|
||||
void httpsRequest() {
|
||||
MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());
|
||||
mockRequest.setScheme("https");
|
||||
mockRequest.setServerPort(443);
|
||||
@@ -114,7 +114,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpsRequestWithCustomPort() {
|
||||
void httpsRequestWithCustomPort() {
|
||||
MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());
|
||||
mockRequest.setScheme("https");
|
||||
mockRequest.setServerPort(8443);
|
||||
@@ -124,7 +124,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithParametersProducesUriWithQueryString() {
|
||||
void getRequestWithParametersProducesUriWithQueryString() {
|
||||
OperationRequest request = createOperationRequest(
|
||||
MockMvcRequestBuilders.get("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&a=apple&b=br%26vo"));
|
||||
@@ -132,7 +132,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRequestWithQueryString() {
|
||||
void getRequestWithQueryString() {
|
||||
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/foo?a=alpha&b=bravo");
|
||||
OperationRequest request = createOperationRequest(builder);
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha&b=bravo"));
|
||||
@@ -140,7 +140,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithParametersCreatesFormUrlEncodedContent() {
|
||||
void postRequestWithParametersCreatesFormUrlEncodedContent() {
|
||||
OperationRequest request = createOperationRequest(
|
||||
MockMvcRequestBuilders.post("/foo").param("a", "alpha", "apple").param("b", "br&vo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
@@ -150,7 +150,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postRequestWithParametersAndQueryStringCreatesFormUrlEncodedContentWithoutDuplication() {
|
||||
void postRequestWithParametersAndQueryStringCreatesFormUrlEncodedContentWithoutDuplication() {
|
||||
OperationRequest request = createOperationRequest(
|
||||
MockMvcRequestBuilders.post("/foo?a=alpha").param("a", "apple").param("b", "br&vo"));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo?a=alpha"));
|
||||
@@ -160,7 +160,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mockMultipartFileUpload() {
|
||||
void mockMultipartFileUpload() {
|
||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.multipart("/foo")
|
||||
.file(new MockMultipartFile("file", new byte[] { 1, 2, 3, 4 })));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
@@ -175,7 +175,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mockMultipartFileUploadWithContentType() {
|
||||
void mockMultipartFileUploadWithContentType() {
|
||||
OperationRequest request = createOperationRequest(MockMvcRequestBuilders.multipart("/foo")
|
||||
.file(new MockMultipartFile("file", "original", "image/png", new byte[] { 1, 2, 3, 4 })));
|
||||
assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo"));
|
||||
@@ -189,7 +189,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithPart() throws IOException {
|
||||
void requestWithPart() throws IOException {
|
||||
MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());
|
||||
Part mockPart = mock(Part.class);
|
||||
given(mockPart.getHeaderNames()).willReturn(Arrays.asList("a", "b"));
|
||||
@@ -211,7 +211,7 @@ public class MockMvcRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWithPartWithContentType() throws IOException {
|
||||
void requestWithPartWithContentType() throws IOException {
|
||||
MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());
|
||||
Part mockPart = mock(Part.class);
|
||||
given(mockPart.getHeaderNames()).willReturn(Arrays.asList("a", "b"));
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Collections;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -37,12 +37,12 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
*
|
||||
* @author Tomasz Kopczynski
|
||||
*/
|
||||
public class MockMvcResponseConverterTests {
|
||||
class MockMvcResponseConverterTests {
|
||||
|
||||
private final MockMvcResponseConverter factory = new MockMvcResponseConverter();
|
||||
|
||||
@Test
|
||||
public void basicResponse() {
|
||||
void basicResponse() {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
OperationResponse operationResponse = this.factory.convert(response);
|
||||
@@ -50,7 +50,7 @@ public class MockMvcResponseConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCookie() {
|
||||
void responseWithCookie() {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
Cookie cookie = new Cookie("name", "value");
|
||||
@@ -66,7 +66,7 @@ public class MockMvcResponseConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCustomStatus() {
|
||||
void responseWithCustomStatus() {
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
response.setStatus(600);
|
||||
OperationResponse operationResponse = this.factory.convert(response);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,12 +19,13 @@ package org.springframework.restdocs.mockmvc;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.restdocs.generate.RestDocumentationGenerator;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -41,24 +42,22 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
* @author Dmitriy Mayboroda
|
||||
*/
|
||||
public class MockMvcRestDocumentationConfigurerTests {
|
||||
@ExtendWith(RestDocumentationExtension.class)
|
||||
class MockMvcRestDocumentationConfigurerTests {
|
||||
|
||||
private MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
@Rule
|
||||
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation)
|
||||
void defaultConfiguration(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
assertUriConfiguration("http", "localhost", 8080);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customScheme() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation).uris()
|
||||
void customScheme(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation).uris()
|
||||
.withScheme("https")
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -66,8 +65,8 @@ public class MockMvcRestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customHost() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation).uris()
|
||||
void customHost(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation).uris()
|
||||
.withHost("api.example.com")
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -75,8 +74,8 @@ public class MockMvcRestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customPort() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation).uris()
|
||||
void customPort(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation).uris()
|
||||
.withPort(8081)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -84,8 +83,8 @@ public class MockMvcRestDocumentationConfigurerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noContentLengthHeaderWhenRequestHasNotContent() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation).uris()
|
||||
void noContentLengthHeaderWhenRequestHasNotContent(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation).uris()
|
||||
.withPort(8081)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -94,8 +93,8 @@ public class MockMvcRestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void uriTemplateFromRequestAttribute() {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation)
|
||||
void uriTemplateFromRequestAttribute(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
this.request.setAttribute(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "{a}/{b}");
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
@@ -106,11 +105,11 @@ public class MockMvcRestDocumentationConfigurerTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void uriTemplateFromRequest() {
|
||||
void uriTemplateFromRequest(RestDocumentationContextProvider restDocumentation) {
|
||||
Method setUriTemplate = ReflectionUtils.findMethod(MockHttpServletRequest.class, "setUriTemplate",
|
||||
String.class);
|
||||
Assume.assumeNotNull(setUriTemplate);
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(this.restDocumentation)
|
||||
Assumptions.assumeFalse(setUriTemplate == null);
|
||||
RequestPostProcessor postProcessor = new MockMvcRestDocumentationConfigurer(restDocumentation)
|
||||
.beforeMockMvcCreated(null, null);
|
||||
ReflectionUtils.invokeMethod(setUriTemplate, this.request, "{a}/{b}");
|
||||
postProcessor.postProcessRequest(this.request);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2024 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,11 +34,10 @@ import java.util.regex.Pattern;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -47,7 +46,8 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationIntegrationTests.TestConfiguration;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
@@ -56,7 +56,7 @@ import org.springframework.restdocs.testfixtures.SnippetConditions.CodeBlockCond
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.HttpRequestCondition;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions.HttpResponseCondition;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
@@ -106,29 +106,30 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* @author Tomasz Kopczynski
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringJUnitConfig
|
||||
@WebAppConfiguration
|
||||
@ExtendWith(RestDocumentationExtension.class)
|
||||
@ContextConfiguration(classes = TestConfiguration.class)
|
||||
public class MockMvcRestDocumentationIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
private RestDocumentationContextProvider restDocumentation;
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void deleteSnippets() {
|
||||
@BeforeEach
|
||||
void setUp(RestDocumentationContextProvider restDocumentation) {
|
||||
this.restDocumentation = restDocumentation;
|
||||
FileSystemUtils.deleteRecursively(new File("build/generated-snippets"));
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearOutputDirSystemProperty() {
|
||||
@AfterEach
|
||||
void clearOutputDirSystemProperty() {
|
||||
System.clearProperty("org.springframework.restdocs.outputDir");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicSnippetGeneration() throws Exception {
|
||||
void basicSnippetGeneration() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(new MockMvcRestDocumentationConfigurer(this.restDocumentation).snippets().withEncoding("UTF-8"))
|
||||
.build();
|
||||
@@ -140,7 +141,19 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void markdownSnippetGeneration() throws Exception {
|
||||
void getRequestWithBody() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(new MockMvcRestDocumentationConfigurer(this.restDocumentation).snippets().withEncoding("UTF-8"))
|
||||
.build();
|
||||
mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON).content("some body content"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("get-request-with-body"));
|
||||
assertExpectedSnippetFilesExist(new File("build/generated-snippets/get-request-with-body"), "http-request.adoc",
|
||||
"http-response.adoc", "curl-request.adoc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void markdownSnippetGeneration() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(new MockMvcRestDocumentationConfigurer(this.restDocumentation).snippets()
|
||||
.withEncoding("UTF-8")
|
||||
@@ -154,7 +167,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithContent() throws Exception {
|
||||
void curlSnippetWithContent() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -168,7 +181,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithCookies() throws Exception {
|
||||
void curlSnippetWithCookies() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -182,7 +195,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithQueryStringOnPost() throws Exception {
|
||||
void curlSnippetWithQueryStringOnPost() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -196,7 +209,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithEmptyParameterQueryString() throws Exception {
|
||||
void curlSnippetWithEmptyParameterQueryString() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -210,7 +223,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithContentAndParametersOnPost() throws Exception {
|
||||
void curlSnippetWithContentAndParametersOnPost() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -224,7 +237,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpieSnippetWithContent() throws Exception {
|
||||
void httpieSnippetWithContent() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -237,7 +250,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpieSnippetWithCookies() throws Exception {
|
||||
void httpieSnippetWithCookies() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -251,7 +264,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpieSnippetWithQueryStringOnPost() throws Exception {
|
||||
void httpieSnippetWithQueryStringOnPost() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -265,7 +278,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpieSnippetWithContentAndParametersOnPost() throws Exception {
|
||||
void httpieSnippetWithContentAndParametersOnPost() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -280,7 +293,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksSnippet() throws Exception {
|
||||
void linksSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -293,7 +306,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersSnippet() throws Exception {
|
||||
void pathParametersSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -305,7 +318,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersSnippet() throws Exception {
|
||||
void queryParametersSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -317,7 +330,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsSnippet() throws Exception {
|
||||
void requestFieldsSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -329,7 +342,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsSnippet() throws Exception {
|
||||
void requestPartsSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -341,7 +354,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsSnippet() throws Exception {
|
||||
void responseFieldsSnippet() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -354,7 +367,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithSetCookie() throws Exception {
|
||||
void responseWithSetCookie() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -368,7 +381,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedOutputDirectory() throws Exception {
|
||||
void parameterizedOutputDirectory() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -380,7 +393,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiStep() throws Exception {
|
||||
void multiStep() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.alwaysDo(document("{method-name}-{step}"))
|
||||
@@ -398,7 +411,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alwaysDoWithAdditionalSnippets() throws Exception {
|
||||
void alwaysDoWithAdditionalSnippets() throws Exception {
|
||||
RestDocumentationResultHandler documentation = document("{method-name}-{step}");
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
@@ -412,7 +425,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedRequest() throws Exception {
|
||||
void preprocessedRequest() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -455,7 +468,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPreprocessedRequest() throws Exception {
|
||||
void defaultPreprocessedRequest() throws Exception {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation).operationPreprocessors()
|
||||
@@ -486,7 +499,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedResponse() throws Exception {
|
||||
void preprocessedResponse() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -515,7 +528,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPreprocessedResponse() throws Exception {
|
||||
void defaultPreprocessedResponse() throws Exception {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation).operationPreprocessors()
|
||||
@@ -537,7 +550,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetTemplate() throws Exception {
|
||||
void customSnippetTemplate() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -559,7 +572,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customContextPath() throws Exception {
|
||||
void customContextPath() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
@@ -573,7 +586,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionShouldBeThrownWhenCallDocumentMockMvcNotConfigured() {
|
||||
void exceptionShouldBeThrownWhenCallDocumentMockMvcNotConfigured() {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
assertThatThrownBy(() -> mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON)).andDo(document("basic")))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
@@ -583,7 +596,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionShouldBeThrownWhenCallDocumentSnippetsMockMvcNotConfigured() {
|
||||
void exceptionShouldBeThrownWhenCallDocumentSnippetsMockMvcNotConfigured() {
|
||||
RestDocumentationResultHandler documentation = document("{method-name}-{step}");
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
assertThatThrownBy(() -> mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
|
||||
@@ -594,7 +607,7 @@ public class MockMvcRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiPart() throws Exception {
|
||||
void multiPart() throws Exception {
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.mockmvc;
|
||||
import java.net.URI;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
@@ -44,97 +44,97 @@ import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuild
|
||||
* @author Andy Wilkinson
|
||||
*
|
||||
*/
|
||||
public class RestDocumentationRequestBuildersTests {
|
||||
class RestDocumentationRequestBuildersTests {
|
||||
|
||||
private final ServletContext servletContext = new MockServletContext();
|
||||
|
||||
@Test
|
||||
public void getTemplate() {
|
||||
void getTemplate() {
|
||||
assertTemplate(get("/{template}", "t"), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUri() {
|
||||
void getUri() {
|
||||
assertUri(get(URI.create("/uri")), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postTemplate() {
|
||||
void postTemplate() {
|
||||
assertTemplate(post("/{template}", "t"), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postUri() {
|
||||
void postUri() {
|
||||
assertUri(post(URI.create("/uri")), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putTemplate() {
|
||||
void putTemplate() {
|
||||
assertTemplate(put("/{template}", "t"), HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putUri() {
|
||||
void putUri() {
|
||||
assertUri(put(URI.create("/uri")), HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchTemplate() {
|
||||
void patchTemplate() {
|
||||
assertTemplate(patch("/{template}", "t"), HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchUri() {
|
||||
void patchUri() {
|
||||
assertUri(patch(URI.create("/uri")), HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteTemplate() {
|
||||
void deleteTemplate() {
|
||||
assertTemplate(delete("/{template}", "t"), HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteUri() {
|
||||
void deleteUri() {
|
||||
assertUri(delete(URI.create("/uri")), HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsTemplate() {
|
||||
void optionsTemplate() {
|
||||
assertTemplate(options("/{template}", "t"), HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionsUri() {
|
||||
void optionsUri() {
|
||||
assertUri(options(URI.create("/uri")), HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headTemplate() {
|
||||
void headTemplate() {
|
||||
assertTemplate(head("/{template}", "t"), HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headUri() {
|
||||
void headUri() {
|
||||
assertUri(head(URI.create("/uri")), HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestTemplate() {
|
||||
void requestTemplate() {
|
||||
assertTemplate(request(HttpMethod.GET, "/{template}", "t"), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestUri() {
|
||||
void requestUri() {
|
||||
assertUri(request(HttpMethod.GET, URI.create("/uri")), HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartTemplate() {
|
||||
void multipartTemplate() {
|
||||
assertTemplate(multipart("/{template}", "t"), HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartUri() {
|
||||
void multipartUri() {
|
||||
assertUri(multipart(URI.create("/uri")), HttpMethod.POST);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ dependencies {
|
||||
api("org.apache.pdfbox:pdfbox:2.0.27")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-core:11.0.2")
|
||||
api("org.apache.tomcat.embed:tomcat-embed-el:11.0.2")
|
||||
api("org.apiguardian:apiguardian-api:1.1.2")
|
||||
api("org.asciidoctor:asciidoctorj:3.0.0")
|
||||
api("org.asciidoctor:asciidoctorj-pdf:2.3.19")
|
||||
api("org.assertj:assertj-core:3.23.1")
|
||||
@@ -22,10 +23,10 @@ dependencies {
|
||||
api("org.hamcrest:hamcrest-library:1.3")
|
||||
api("org.hibernate.validator:hibernate-validator:9.0.0.CR1")
|
||||
api("org.javamoney:moneta:1.4.2")
|
||||
api("org.junit.jupiter:junit-jupiter-api:5.0.0")
|
||||
}
|
||||
api(enforcedPlatform("com.fasterxml.jackson:jackson-bom:2.14.0"))
|
||||
api(enforcedPlatform("io.rest-assured:rest-assured-bom:5.2.1"))
|
||||
api(enforcedPlatform("org.mockito:mockito-bom:4.9.0"))
|
||||
api(enforcedPlatform("org.junit:junit-bom:5.13.0"))
|
||||
api(enforcedPlatform("org.springframework:spring-framework-bom:$springFrameworkVersion"))
|
||||
}
|
||||
|
||||
@@ -13,13 +13,14 @@ dependencies {
|
||||
|
||||
internal(platform(project(":spring-restdocs-platform")))
|
||||
|
||||
testCompileOnly("org.apiguardian:apiguardian-api")
|
||||
testImplementation(testFixtures(project(":spring-restdocs-core")))
|
||||
testImplementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
testImplementation("junit:junit")
|
||||
testImplementation("org.apache.tomcat.embed:tomcat-embed-core")
|
||||
testImplementation("org.assertj:assertj-core")
|
||||
testImplementation("org.hamcrest:hamcrest-library")
|
||||
testImplementation("org.mockito:mockito-core")
|
||||
}
|
||||
|
||||
tasks.named("test") {
|
||||
useJUnitPlatform();
|
||||
}
|
||||
|
||||
compatibilityTest {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,8 @@ package org.springframework.restdocs.restassured;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -34,12 +34,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RestAssuredParameterBehaviorTests {
|
||||
class RestAssuredParameterBehaviorTests {
|
||||
|
||||
private static final MediaType APPLICATION_FORM_URLENCODED_ISO_8859_1 = MediaType
|
||||
.parseMediaType(MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=ISO-8859-1");
|
||||
|
||||
@ClassRule
|
||||
@RegisterExtension
|
||||
public static TomcatServer tomcat = new TomcatServer();
|
||||
|
||||
private final RestAssuredRequestConverter factory = new RestAssuredRequestConverter();
|
||||
@@ -54,7 +54,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
});
|
||||
|
||||
@Test
|
||||
public void queryParameterOnGet() {
|
||||
void queryParameterOnGet() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.get("/query-parameter")
|
||||
@@ -64,7 +64,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnHead() {
|
||||
void queryParameterOnHead() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.head("/query-parameter")
|
||||
@@ -74,7 +74,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnPost() {
|
||||
void queryParameterOnPost() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.post("/query-parameter")
|
||||
@@ -84,7 +84,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnPut() {
|
||||
void queryParameterOnPut() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.put("/query-parameter")
|
||||
@@ -94,7 +94,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnPatch() {
|
||||
void queryParameterOnPatch() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.patch("/query-parameter")
|
||||
@@ -104,7 +104,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnDelete() {
|
||||
void queryParameterOnDelete() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.delete("/query-parameter")
|
||||
@@ -114,7 +114,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParameterOnOptions() {
|
||||
void queryParameterOnOptions() {
|
||||
this.spec.queryParam("a", "alpha", "apple")
|
||||
.queryParam("b", "bravo")
|
||||
.options("/query-parameter")
|
||||
@@ -124,49 +124,49 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnGet() {
|
||||
void paramOnGet() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").get("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.GET);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnHead() {
|
||||
void paramOnHead() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").head("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnPost() {
|
||||
void paramOnPost() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").post("/form-url-encoded").then().statusCode(200);
|
||||
assertThatRequest(this.request).isFormUrlEncodedWithMethod(HttpMethod.POST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnPut() {
|
||||
void paramOnPut() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").put("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PUT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnPatch() {
|
||||
void paramOnPatch() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").patch("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnDelete() {
|
||||
void paramOnDelete() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").delete("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnOptions() {
|
||||
void paramOnOptions() {
|
||||
this.spec.param("a", "alpha", "apple").param("b", "bravo").options("/query-parameter").then().statusCode(200);
|
||||
assertThatRequest(this.request).hasQueryParametersWithMethod(HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnGet() {
|
||||
void formParamOnGet() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.get("/query-parameter")
|
||||
@@ -176,7 +176,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnHead() {
|
||||
void formParamOnHead() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.head("/form-url-encoded")
|
||||
@@ -186,7 +186,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnPost() {
|
||||
void formParamOnPost() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.post("/form-url-encoded")
|
||||
@@ -196,7 +196,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnPut() {
|
||||
void formParamOnPut() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.put("/form-url-encoded")
|
||||
@@ -206,7 +206,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnPatch() {
|
||||
void formParamOnPatch() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.patch("/form-url-encoded")
|
||||
@@ -216,7 +216,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnDelete() {
|
||||
void formParamOnDelete() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.delete("/form-url-encoded")
|
||||
@@ -226,7 +226,7 @@ public class RestAssuredParameterBehaviorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formParamOnOptions() {
|
||||
void formParamOnOptions() {
|
||||
this.spec.formParam("a", "alpha", "apple")
|
||||
.formParam("b", "bravo")
|
||||
.options("/form-url-encoded")
|
||||
|
||||
@@ -28,8 +28,8 @@ import java.util.Iterator;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.specification.FilterableRequestSpecification;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -47,15 +47,15 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RestAssuredRequestConverterTests {
|
||||
class RestAssuredRequestConverterTests {
|
||||
|
||||
@ClassRule
|
||||
@RegisterExtension
|
||||
public static TomcatServer tomcat = new TomcatServer();
|
||||
|
||||
private final RestAssuredRequestConverter factory = new RestAssuredRequestConverter();
|
||||
|
||||
@Test
|
||||
public void requestUri() {
|
||||
void requestUri() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort());
|
||||
requestSpec.get("/foo/bar");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -63,7 +63,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestMethod() {
|
||||
void requestMethod() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort());
|
||||
requestSpec.head("/foo/bar");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -71,7 +71,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryStringParameters() {
|
||||
void queryStringParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).queryParam("foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -79,7 +79,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryStringFromUrlParameters() {
|
||||
void queryStringFromUrlParameters() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort());
|
||||
requestSpec.get("/?foo=bar&foo=qix");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -87,7 +87,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramOnGetRequestIsMappedToQueryString() {
|
||||
void paramOnGetRequestIsMappedToQueryString() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).param("foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -95,7 +95,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headers() {
|
||||
void headers() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).header("Foo", "bar");
|
||||
requestSpec.get("/");
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -104,7 +104,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headersWithCustomAccept() {
|
||||
void headersWithCustomAccept() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.header("Foo", "bar")
|
||||
@@ -117,7 +117,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cookies() {
|
||||
void cookies() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.cookie("cookie1", "cookieVal1")
|
||||
@@ -138,7 +138,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipart() {
|
||||
void multipart() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.multiPart("a", "a.txt", "alpha", null)
|
||||
@@ -156,14 +156,14 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void byteArrayBody() {
|
||||
void byteArrayBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().body("body".getBytes()).port(tomcat.getPort());
|
||||
requestSpec.post();
|
||||
this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringBody() {
|
||||
void stringBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().body("body").port(tomcat.getPort());
|
||||
requestSpec.post();
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -171,7 +171,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectBody() {
|
||||
void objectBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().body(new ObjectBody("bar")).port(tomcat.getPort());
|
||||
requestSpec.post();
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -179,7 +179,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void byteArrayInputStreamBody() {
|
||||
void byteArrayInputStreamBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.body(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }))
|
||||
.port(tomcat.getPort());
|
||||
@@ -189,7 +189,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileBody() {
|
||||
void fileBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.body(new File("src/test/resources/body.txt"))
|
||||
.port(tomcat.getPort());
|
||||
@@ -199,7 +199,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileInputStreamBody() throws FileNotFoundException {
|
||||
void fileInputStreamBody() throws FileNotFoundException {
|
||||
FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt");
|
||||
RequestSpecification requestSpec = RestAssured.given().body(inputStream).port(tomcat.getPort());
|
||||
requestSpec.post();
|
||||
@@ -209,7 +209,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithByteArrayInputStreamBody() {
|
||||
void multipartWithByteArrayInputStreamBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.multiPart("foo", "foo.txt", new ByteArrayInputStream("foo".getBytes()));
|
||||
@@ -219,7 +219,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithStringBody() {
|
||||
void multipartWithStringBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given().port(tomcat.getPort()).multiPart("control", "foo");
|
||||
requestSpec.post();
|
||||
OperationRequest request = this.factory.convert((FilterableRequestSpecification) requestSpec);
|
||||
@@ -227,7 +227,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithByteArrayBody() {
|
||||
void multipartWithByteArrayBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.multiPart("control", "file", "foo".getBytes());
|
||||
@@ -237,7 +237,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithFileBody() {
|
||||
void multipartWithFileBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.multiPart(new File("src/test/resources/body.txt"));
|
||||
@@ -247,7 +247,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithFileInputStreamBody() throws FileNotFoundException {
|
||||
void multipartWithFileInputStreamBody() throws FileNotFoundException {
|
||||
FileInputStream inputStream = new FileInputStream("src/test/resources/body.txt");
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
@@ -259,7 +259,7 @@ public class RestAssuredRequestConverterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartWithObjectBody() {
|
||||
void multipartWithObjectBody() {
|
||||
RequestSpecification requestSpec = RestAssured.given()
|
||||
.port(tomcat.getPort())
|
||||
.multiPart("control", new ObjectBody("bar"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.restdocs.restassured;
|
||||
import io.restassured.http.Headers;
|
||||
import io.restassured.response.Response;
|
||||
import io.restassured.response.ResponseBody;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
@@ -33,12 +33,12 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class RestAssuredResponseConverterTests {
|
||||
class RestAssuredResponseConverterTests {
|
||||
|
||||
private final RestAssuredResponseConverter converter = new RestAssuredResponseConverter();
|
||||
|
||||
@Test
|
||||
public void responseWithCustomStatus() {
|
||||
void responseWithCustomStatus() {
|
||||
Response response = mock(Response.class);
|
||||
given(response.getStatusCode()).willReturn(600);
|
||||
given(response.getHeaders()).willReturn(new Headers());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,13 @@ import java.util.Map;
|
||||
import io.restassured.filter.FilterContext;
|
||||
import io.restassured.specification.FilterableRequestSpecification;
|
||||
import io.restassured.specification.FilterableResponseSpecification;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.restdocs.generate.RestDocumentationGenerator;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationRequestPreprocessor;
|
||||
import org.springframework.restdocs.operation.preprocess.OperationResponsePreprocessor;
|
||||
@@ -45,10 +47,8 @@ import static org.mockito.Mockito.verify;
|
||||
* @author Andy Wilkinson
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class RestAssuredRestDocumentationConfigurerTests {
|
||||
|
||||
@Rule
|
||||
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
@ExtendWith(RestDocumentationExtension.class)
|
||||
class RestAssuredRestDocumentationConfigurerTests {
|
||||
|
||||
private final FilterableRequestSpecification requestSpec = mock(FilterableRequestSpecification.class);
|
||||
|
||||
@@ -56,17 +56,21 @@ public class RestAssuredRestDocumentationConfigurerTests {
|
||||
|
||||
private final FilterContext filterContext = mock(FilterContext.class);
|
||||
|
||||
private final RestAssuredRestDocumentationConfigurer configurer = new RestAssuredRestDocumentationConfigurer(
|
||||
this.restDocumentation);
|
||||
private RestAssuredRestDocumentationConfigurer configurer;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(RestDocumentationContextProvider restDocumentation) {
|
||||
this.configurer = new RestAssuredRestDocumentationConfigurer(restDocumentation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nextFilterIsCalled() {
|
||||
void nextFilterIsCalled() {
|
||||
this.configurer.filter(this.requestSpec, this.responseSpec, this.filterContext);
|
||||
verify(this.filterContext).next(this.requestSpec, this.responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurationIsAddedToTheContext() {
|
||||
void configurationIsAddedToTheContext() {
|
||||
this.configurer.operationPreprocessors()
|
||||
.withRequestDefaults(Preprocessors.prettyPrint())
|
||||
.withResponseDefaults(Preprocessors.modifyHeaders().remove("Foo"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,14 +29,15 @@ import java.util.regex.Pattern;
|
||||
import io.restassured.builder.RequestSpecBuilder;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.restdocs.templates.TemplateFormat;
|
||||
import org.springframework.restdocs.templates.TemplateFormats;
|
||||
import org.springframework.restdocs.testfixtures.SnippetConditions;
|
||||
@@ -80,18 +81,16 @@ import static org.springframework.restdocs.restassured.RestAssuredRestDocumentat
|
||||
* @author Tomasz Kopczynski
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class RestAssuredRestDocumentationIntegrationTests {
|
||||
@ExtendWith(RestDocumentationExtension.class)
|
||||
class RestAssuredRestDocumentationIntegrationTests {
|
||||
|
||||
@Rule
|
||||
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
|
||||
@ClassRule
|
||||
public static TomcatServer tomcat = new TomcatServer();
|
||||
@RegisterExtension
|
||||
private static TomcatServer tomcat = new TomcatServer();
|
||||
|
||||
@Test
|
||||
public void defaultSnippetGeneration() {
|
||||
void defaultSnippetGeneration(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("default"))
|
||||
.get("/")
|
||||
.then()
|
||||
@@ -101,10 +100,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithContent() {
|
||||
void curlSnippetWithContent(RestDocumentationContextProvider restDocumentation) {
|
||||
String contentType = "text/plain; charset=UTF-8";
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("curl-snippet-with-content"))
|
||||
.accept("application/json")
|
||||
.body("content")
|
||||
@@ -120,10 +119,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithCookies() {
|
||||
void curlSnippetWithCookies(RestDocumentationContextProvider restDocumentation) {
|
||||
String contentType = "text/plain; charset=UTF-8";
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("curl-snippet-with-cookies"))
|
||||
.accept("application/json")
|
||||
.contentType(contentType)
|
||||
@@ -138,9 +137,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithEmptyParameterQueryString() {
|
||||
void curlSnippetWithEmptyParameterQueryString(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("curl-snippet-with-empty-parameter-query-string"))
|
||||
.accept("application/json")
|
||||
.param("a", "")
|
||||
@@ -155,9 +154,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void curlSnippetWithQueryStringOnPost() {
|
||||
void curlSnippetWithQueryStringOnPost(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("curl-snippet-with-query-string"))
|
||||
.accept("application/json")
|
||||
.param("foo", "bar")
|
||||
@@ -174,9 +173,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void linksSnippet() {
|
||||
void linksSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("links", links(linkWithRel("rel").description("The description"))))
|
||||
.accept("application/json")
|
||||
.get("/")
|
||||
@@ -187,9 +186,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pathParametersSnippet() {
|
||||
void pathParametersSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("path-parameters",
|
||||
pathParameters(parameterWithName("foo").description("The description"))))
|
||||
.accept("application/json")
|
||||
@@ -201,9 +200,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryParametersSnippet() {
|
||||
void queryParametersSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("query-parameters",
|
||||
queryParameters(parameterWithName("foo").description("The description"))))
|
||||
.accept("application/json")
|
||||
@@ -216,9 +215,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestFieldsSnippet() {
|
||||
void requestFieldsSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("request-fields", requestFields(fieldWithPath("a").description("The description"))))
|
||||
.accept("application/json")
|
||||
.body("{\"a\":\"alpha\"}")
|
||||
@@ -230,9 +229,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestPartsSnippet() {
|
||||
void requestPartsSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("request-parts", requestParts(partWithName("a").description("The description"))))
|
||||
.multiPart("a", "foo")
|
||||
.post("/upload")
|
||||
@@ -243,9 +242,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseFieldsSnippet() {
|
||||
void responseFieldsSnippet(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("response-fields",
|
||||
responseFields(fieldWithPath("a").description("The description"),
|
||||
subsectionWithPath("links").description("Links to other resources"))))
|
||||
@@ -258,9 +257,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterizedOutputDirectory() {
|
||||
void parameterizedOutputDirectory(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("{method-name}"))
|
||||
.get("/")
|
||||
.then()
|
||||
@@ -270,9 +269,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiStep() {
|
||||
void multiStep(RestDocumentationContextProvider restDocumentation) {
|
||||
RequestSpecification spec = new RequestSpecBuilder().setPort(tomcat.getPort())
|
||||
.addFilter(documentationConfiguration(this.restDocumentation))
|
||||
.addFilter(documentationConfiguration(restDocumentation))
|
||||
.addFilter(document("{method-name}-{step}"))
|
||||
.build();
|
||||
given(spec).get("/").then().statusCode(200);
|
||||
@@ -287,10 +286,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalSnippets() {
|
||||
void additionalSnippets(RestDocumentationContextProvider restDocumentation) {
|
||||
RestDocumentationFilter documentation = document("{method-name}-{step}");
|
||||
RequestSpecification spec = new RequestSpecBuilder().setPort(tomcat.getPort())
|
||||
.addFilter(documentationConfiguration(this.restDocumentation))
|
||||
.addFilter(documentationConfiguration(restDocumentation))
|
||||
.addFilter(documentation)
|
||||
.build();
|
||||
given(spec)
|
||||
@@ -304,9 +303,9 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseWithCookie() {
|
||||
void responseWithCookie(RestDocumentationContextProvider restDocumentation) {
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("set-cookie",
|
||||
preprocessResponse(modifyHeaders().remove(HttpHeaders.DATE).remove(HttpHeaders.CONTENT_TYPE))))
|
||||
.get("/set-cookie")
|
||||
@@ -322,10 +321,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedRequest() {
|
||||
void preprocessedRequest(RestDocumentationContextProvider restDocumentation) {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.header("a", "alpha")
|
||||
.header("b", "bravo")
|
||||
.contentType("application/json")
|
||||
@@ -356,10 +355,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPreprocessedRequest() {
|
||||
void defaultPreprocessedRequest(RestDocumentationContextProvider restDocumentation) {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation).operationPreprocessors()
|
||||
.filter(documentationConfiguration(restDocumentation).operationPreprocessors()
|
||||
.withRequestDefaults(prettyPrint(), replacePattern(pattern, "\"<<beta>>\""), modifyUris().removePort(),
|
||||
modifyHeaders().remove("a").remove(HttpHeaders.CONTENT_LENGTH)))
|
||||
.header("a", "alpha")
|
||||
@@ -381,10 +380,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preprocessedResponse() {
|
||||
void preprocessedResponse(RestDocumentationContextProvider restDocumentation) {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("original-response"))
|
||||
.filter(document("preprocessed-response",
|
||||
preprocessResponse(prettyPrint(), maskLinks(),
|
||||
@@ -407,10 +406,10 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultPreprocessedResponse() {
|
||||
void defaultPreprocessedResponse(RestDocumentationContextProvider restDocumentation) {
|
||||
Pattern pattern = Pattern.compile("(\"alpha\")");
|
||||
given().port(tomcat.getPort())
|
||||
.filter(documentationConfiguration(this.restDocumentation).operationPreprocessors()
|
||||
.filter(documentationConfiguration(restDocumentation).operationPreprocessors()
|
||||
.withResponseDefaults(prettyPrint(), maskLinks(),
|
||||
modifyHeaders().remove("a").remove("Transfer-Encoding").remove("Date").remove("Server"),
|
||||
replacePattern(pattern, "\"<<beta>>\""),
|
||||
@@ -432,7 +431,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customSnippetTemplate() throws MalformedURLException {
|
||||
void customSnippetTemplate(RestDocumentationContextProvider restDocumentation) throws MalformedURLException {
|
||||
ClassLoader classLoader = new URLClassLoader(
|
||||
new URL[] { new File("src/test/resources/custom-snippet-templates").toURI().toURL() },
|
||||
getClass().getClassLoader());
|
||||
@@ -441,7 +440,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
try {
|
||||
given().port(tomcat.getPort())
|
||||
.accept("application/json")
|
||||
.filter(documentationConfiguration(this.restDocumentation))
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.filter(document("custom-snippet-template"))
|
||||
.get("/")
|
||||
.then()
|
||||
@@ -455,7 +454,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionShouldBeThrownWhenCallDocumentRequestSpecificationNotConfigured() {
|
||||
void exceptionShouldBeThrownWhenCallDocumentRequestSpecificationNotConfigured() {
|
||||
assertThatThrownBy(() -> given().port(tomcat.getPort()).filter(document("default")).get("/"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("REST Docs configuration not found. Did you forget to add a "
|
||||
@@ -463,7 +462,7 @@ public class RestAssuredRestDocumentationIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exceptionShouldBeThrownWhenCallDocumentSnippetsRequestSpecificationNotConfigured() {
|
||||
void exceptionShouldBeThrownWhenCallDocumentSnippetsRequestSpecificationNotConfigured() {
|
||||
RestDocumentationFilter documentation = document("{method-name}-{step}");
|
||||
assertThatThrownBy(() -> given().port(tomcat.getPort())
|
||||
.filter(documentation.document(responseHeaders(headerWithName("a").description("one"))))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 the original author or authors.
|
||||
* Copyright 2014-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,46 +32,57 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.Extension;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* {@link ExternalResource} that starts and stops a Tomcat server.
|
||||
* {@link Extension} that starts and stops a Tomcat server.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class TomcatServer extends ExternalResource {
|
||||
|
||||
private Tomcat tomcat;
|
||||
class TomcatServer implements BeforeAllCallback, AfterAllCallback {
|
||||
|
||||
private int port;
|
||||
|
||||
@Override
|
||||
protected void before() throws LifecycleException {
|
||||
this.tomcat = new Tomcat();
|
||||
this.tomcat.getConnector().setPort(0);
|
||||
Context context = this.tomcat.addContext("/", null);
|
||||
this.tomcat.addServlet("/", "test", new TestServlet());
|
||||
context.addServletMappingDecoded("/", "test");
|
||||
this.tomcat.addServlet("/", "set-cookie", new CookiesServlet());
|
||||
context.addServletMappingDecoded("/set-cookie", "set-cookie");
|
||||
this.tomcat.addServlet("/", "query-parameter", new QueryParameterServlet());
|
||||
context.addServletMappingDecoded("/query-parameter", "query-parameter");
|
||||
this.tomcat.addServlet("/", "form-url-encoded", new FormUrlEncodedServlet());
|
||||
context.addServletMappingDecoded("/form-url-encoded", "form-url-encoded");
|
||||
this.tomcat.start();
|
||||
this.port = this.tomcat.getConnector().getLocalPort();
|
||||
public void beforeAll(ExtensionContext extensionContext) {
|
||||
Store store = extensionContext.getStore(Namespace.create(TomcatServer.class));
|
||||
store.getOrComputeIfAbsent(Tomcat.class, (key) -> {
|
||||
Tomcat tomcat = new Tomcat();
|
||||
tomcat.getConnector().setPort(0);
|
||||
Context context = tomcat.addContext("/", null);
|
||||
tomcat.addServlet("/", "test", new TestServlet());
|
||||
context.addServletMappingDecoded("/", "test");
|
||||
tomcat.addServlet("/", "set-cookie", new CookiesServlet());
|
||||
context.addServletMappingDecoded("/set-cookie", "set-cookie");
|
||||
tomcat.addServlet("/", "query-parameter", new QueryParameterServlet());
|
||||
context.addServletMappingDecoded("/query-parameter", "query-parameter");
|
||||
tomcat.addServlet("/", "form-url-encoded", new FormUrlEncodedServlet());
|
||||
context.addServletMappingDecoded("/form-url-encoded", "form-url-encoded");
|
||||
try {
|
||||
tomcat.start();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
this.port = tomcat.getConnector().getLocalPort();
|
||||
return tomcat;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
try {
|
||||
this.tomcat.stop();
|
||||
}
|
||||
catch (LifecycleException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
public void afterAll(ExtensionContext extensionContext) throws LifecycleException {
|
||||
Store store = extensionContext.getStore(Namespace.create(TomcatServer.class));
|
||||
Tomcat tomcat = store.get(Tomcat.class, Tomcat.class);
|
||||
if (tomcat != null) {
|
||||
tomcat.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user