Add support for using a wildcard when documenting a payload field

Closes gh-265
This commit is contained in:
Andy Wilkinson
2017-03-23 11:05:48 +00:00
parent 78982cf515
commit ab1613ed63
7 changed files with 238 additions and 46 deletions

View File

@@ -145,4 +145,30 @@ public class JsonFieldPathTests {
contains("a.key", "[]", "b", "c"));
}
@Test
public void compilationOfPathWithAWildcard() {
assertThat(JsonFieldPath.compile("a.b.*.c").getSegments(),
contains("a", "b", "*", "c"));
}
@Test
public void compilationOfPathWithAWildcardInBrackets() {
assertThat(JsonFieldPath.compile("a.b.['*'].c").getSegments(),
contains("a", "b", "*", "c"));
}
@Test
public void fieldBeneathTopLevelWildcardIsNotPreciseAndNotAnArray() {
JsonFieldPath path = JsonFieldPath.compile("*.a");
assertFalse(path.isPrecise());
assertFalse(path.isArray());
}
@Test
public void fieldBeneathNestedWildcardIsNotPreciseAndNotAnArray() {
JsonFieldPath path = JsonFieldPath.compile("a.*.b");
assertFalse(path.isPrecise());
assertFalse(path.isArray());
}
}

View File

@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -27,6 +28,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasKey;
import static org.junit.Assert.assertThat;
/**
@@ -305,6 +310,102 @@ public class JsonFieldProcessorTests {
equalTo((Object) "bravo"));
}
@SuppressWarnings("unchecked")
@Test
public void extractNestedEntriesUsingTopLevelWildcard() throws IOException {
Map<String, Object> payload = new LinkedHashMap<>();
Map<String, Object> alpha = new LinkedHashMap<>();
payload.put("a", alpha);
alpha.put("b", "bravo1");
Map<String, Object> charlie = new LinkedHashMap<>();
charlie.put("b", "bravo2");
payload.put("c", charlie);
assertThat((List<String>) this.fieldProcessor
.extract(JsonFieldPath.compile("*.b"), payload),
contains("bravo1", "bravo2"));
}
@SuppressWarnings("unchecked")
@Test
public void extractNestedEntriesUsingMidLevelWildcard() throws IOException {
Map<String, Object> payload = new LinkedHashMap<>();
Map<String, Object> alpha = new LinkedHashMap<>();
payload.put("a", alpha);
Map<String, Object> bravo = new LinkedHashMap<>();
bravo.put("b", "bravo");
alpha.put("one", bravo);
alpha.put("two", bravo);
assertThat((List<String>) this.fieldProcessor
.extract(JsonFieldPath.compile("a.*.b"), payload),
contains("bravo", "bravo"));
}
@SuppressWarnings("unchecked")
@Test
public void extractUsingLeafWildcardMatchingSingleItem() throws IOException {
Map<String, Object> payload = new HashMap<>();
Map<String, Object> alpha = new HashMap<>();
payload.put("a", alpha);
alpha.put("b", "bravo1");
Map<String, Object> charlie = new HashMap<>();
charlie.put("b", "bravo2");
payload.put("c", charlie);
assertThat((List<String>) this.fieldProcessor
.extract(JsonFieldPath.compile("a.*"), payload), contains("bravo1"));
}
@SuppressWarnings("unchecked")
@Test
public void extractUsingLeafWildcardMatchingMultipleItems() throws IOException {
Map<String, Object> payload = new HashMap<>();
Map<String, Object> alpha = new HashMap<>();
payload.put("a", alpha);
alpha.put("b", "bravo1");
alpha.put("c", "charlie");
assertThat((List<String>) this.fieldProcessor
.extract(JsonFieldPath.compile("a.*"), payload),
contains("bravo1", "charlie"));
}
@Test
public void removeUsingLeafWildcard() throws IOException {
Map<String, Object> payload = new HashMap<>();
Map<String, Object> alpha = new HashMap<>();
payload.put("a", alpha);
alpha.put("b", "bravo1");
alpha.put("c", "charlie");
this.fieldProcessor.remove(JsonFieldPath.compile("a.*"), payload);
assertThat(payload.size(), equalTo(0));
}
@Test
public void removeUsingTopLevelWildcard() throws IOException {
Map<String, Object> payload = new HashMap<>();
Map<String, Object> alpha = new HashMap<>();
payload.put("a", alpha);
alpha.put("b", "bravo1");
alpha.put("c", "charlie");
this.fieldProcessor.remove(JsonFieldPath.compile("*.b"), payload);
assertThat(alpha, not(hasKey("b")));
}
@Test
public void removeUsingMidLevelWildcard() throws IOException {
Map<String, Object> payload = new LinkedHashMap<>();
Map<String, Object> alpha = new LinkedHashMap<>();
payload.put("a", alpha);
payload.put("c", "charlie");
Map<String, Object> bravo1 = new LinkedHashMap<>();
bravo1.put("b", "bravo");
alpha.put("one", bravo1);
Map<String, Object> bravo2 = new LinkedHashMap<>();
bravo2.put("b", "bravo");
alpha.put("two", bravo2);
this.fieldProcessor.remove(JsonFieldPath.compile("a.*.b"), payload);
assertThat(payload.size(), equalTo(1));
assertThat(payload, hasEntry("c", (Object) "charlie"));
}
private Map<String, String> createEntry(String... pairs) {
Map<String, String> entry = new HashMap<>();
for (String pair : pairs) {

View File

@@ -107,7 +107,7 @@ public class RequestFieldsSnippetTests extends AbstractSnippetTests {
.document(this.operationBuilder.request("http://localhost")
.content(
"[{\"a\": {\"b\": 5}},{\"a\": {\"c\": \"charlie\"}}]")
.build());
.build());
}
@Test
@@ -267,8 +267,8 @@ public class RequestFieldsSnippetTests extends AbstractSnippetTests {
public void xmlRequestFields() throws IOException {
this.snippets.expectRequestFields()
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a/b`", "`b`", "one").row("`a/c`", "`c`", "two").row("`a`",
"`a`", "three"));
.row("`a/b`", "`b`", "one").row("`a/c`", "`c`", "two")
.row("`a`", "`a`", "three"));
new RequestFieldsSnippet(
Arrays.asList(fieldWithPath("a/b").description("one").type("b"),
@@ -279,7 +279,7 @@ public class RequestFieldsSnippetTests extends AbstractSnippetTests {
.content("<a><b>5</b><c>charlie</c></a>")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML_VALUE)
.build());
.build());
}
@Test
@@ -338,6 +338,24 @@ public class RequestFieldsSnippetTests extends AbstractSnippetTests {
.content("{\"Foo|Bar\": 5}").build());
}
@Test
public void mapRequestWithVaryingKeysMatchedUsingWildcard() throws IOException {
this.snippets.expectRequestFields()
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`things.*.size`", "`String`", "one")
.row("`things.*.type`", "`String`", "two"));
new RequestFieldsSnippet(
Arrays.asList(fieldWithPath("things.*.size").description("one"),
fieldWithPath("things.*.type").description("two"))).document(
this.operationBuilder.request("http://localhost")
.content("{\"things\": {\"12abf\": {\"type\":"
+ "\"Whale\", \"size\": \"HUGE\"},"
+ "\"gzM33\" : {\"type\": \"Screw\","
+ "\"size\": \"SMALL\"}}}")
.build());
}
private String escapeIfNecessary(String input) {
if (this.templateFormat.equals(TemplateFormats.markdown())) {
return input;

View File

@@ -241,8 +241,8 @@ public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
public void xmlResponseFields() throws IOException {
this.snippets.expectResponseFields()
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`a/b`", "`b`", "one").row("`a/c`", "`c`", "two").row("`a`",
"`a`", "three"));
.row("`a/b`", "`b`", "one").row("`a/c`", "`c`", "two")
.row("`a`", "`a`", "three"));
new ResponseFieldsSnippet(
Arrays.asList(fieldWithPath("a/b").description("one").type("b"),
fieldWithPath("a/c").description("two").type("c"),
@@ -252,7 +252,7 @@ public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
.content("<a><b>5</b><c>charlie</c></a>")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML_VALUE)
.build());
.build());
}
@Test
@@ -268,7 +268,7 @@ public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
.content("<a id=\"1\">foo</a>")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML_VALUE)
.build());
.build());
}
@Test
@@ -284,7 +284,7 @@ public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
.content("<a>foo</a>")
.header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML_VALUE)
.build());
.build());
}
@Test
@@ -348,6 +348,24 @@ public class ResponseFieldsSnippetTests extends AbstractSnippetTests {
.content("{\"Foo|Bar\": 5}").build());
}
@Test
public void mapResponseWithVaryingKeysMatchedUsingWildcard() throws IOException {
this.snippets.expectResponseFields()
.withContents(tableWithHeader("Path", "Type", "Description")
.row("`things.*.size`", "`String`", "one")
.row("`things.*.type`", "`String`", "two"));
new ResponseFieldsSnippet(
Arrays.asList(fieldWithPath("things.*.size").description("one"),
fieldWithPath("things.*.type").description("two")))
.document(this.operationBuilder.response()
.content("{\"things\": {\"12abf\": {\"type\":"
+ "\"Whale\", \"size\": \"HUGE\"},"
+ "\"gzM33\" : {\"type\": \"Screw\","
+ "\"size\": \"SMALL\"}}}")
.build());
}
private String escapeIfNecessary(String input) {
if (this.templateFormat.equals(TemplateFormats.markdown())) {
return input;