Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje committed Jan 7, 2022
1 parent cac1a53 commit d8b4036
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ public <T> T convert(DocString docString, Type targetType) {
private List<String> suggestedContentTypes(List<DocStringType> docStringTypes) {
return docStringTypes.stream()
.map(DocStringType::getContentType)
// Can't use the anonymous content type to resolve
// the ambiguity.
.filter(contentType -> !contentType.isEmpty())
.map(DocStringTypeRegistryDocStringConverter::emptyToAnonymous)
.sorted()
.distinct()
.collect(Collectors.toList());
}

private static String emptyToAnonymous(String contentType) {
return contentType.isEmpty() ? "[anonymous]" : contentType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,42 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.equalToCompressingWhiteSpace;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertThrows;

class DocStringTypeRegistryDocStringConverterTest {

private final DocStringTypeRegistry registry = new DocStringTypeRegistry();
private final DocStringTypeRegistryDocStringConverter converter = new DocStringTypeRegistryDocStringConverter(
registry);
static final DocStringType jsonNodeForJson = new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s));
static final DocStringType stringForText = new DocStringType(
String.class,
"text",
(String s) -> s);
static final DocStringType stringForXml = new DocStringType(
String.class,
"xml",
(String s) -> s);
static final DocStringType stringForYaml = new DocStringType(
String.class,
"yml",
(String s) -> s);
public static final DocStringType jsonNodeForXml = new DocStringType(
JsonNode.class,
"xml",
(String s) -> new ObjectMapper().readTree(s));
public static final DocStringType stringForJson = new DocStringType(
String.class,
"json",
(String s) -> s);

final DocStringTypeRegistry registry = new DocStringTypeRegistry();
final DocStringTypeRegistryDocStringConverter converter = new DocStringTypeRegistryDocStringConverter(registry);

@Test
void throws_when_uses_doc_string_type_but_downcast_conversion() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));
registry.defineDocStringType(jsonNodeForJson);

DocString docString = DocString.create(
"{\"hello\":\"world\"}",
Expand All @@ -39,10 +61,7 @@ void throws_when_uses_doc_string_type_but_downcast_conversion() {

@Test
void uses_target_type_when_available() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));
registry.defineDocStringType(jsonNodeForJson);

DocString docString = DocString.create(
"{\"hello\":\"world\"}");
Expand All @@ -62,10 +81,7 @@ void target_type_to_string_is_predefined() {

@Test
void default_converter_is_used_if_registered_converter_does_not_match_type() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));
registry.defineDocStringType(jsonNodeForJson);

DocString docString = DocString.create(
"hello world", "json");
Expand All @@ -76,10 +92,7 @@ void default_converter_is_used_if_registered_converter_does_not_match_type() {

@Test
void default_converter_never_conflicts_with_registered_converter_for_string() {
registry.defineDocStringType(new DocStringType(
String.class,
"text",
(String s) -> s));
registry.defineDocStringType(stringForText);

DocString docString = DocString.create("hello world");

Expand All @@ -89,25 +102,20 @@ void default_converter_never_conflicts_with_registered_converter_for_string() {

@Test
void throws_if_converter_type_conflicts_with_type() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));

registry.defineDocStringType(new DocStringType(
String.class,
"text",
(String s) -> s));
registry.defineDocStringType(jsonNodeForJson);
registry.defineDocStringType(stringForText);

DocString docString = DocString.create("hello world", "json");

CucumberDocStringException exception = assertThrows(
CucumberDocStringException.class,
() -> converter.convert(docString, String.class));

// TODO: This exception should explain,

assertThat(exception.getMessage(),
is("Multiple converters found for type java.lang.String, and the content type 'json' " +
"did not match any of the registered types [text]. Change the content type of the docstring " +
"did not match any of the registered types [[anonymous], text]. Change the content type of the docstring " +
"or register a docstring type for 'json'"));
}

Expand Down Expand Up @@ -187,15 +195,9 @@ void converts_no_content_type_doc_string_to_registered_matching_convertor() {

@Test
void throws_when_multiple_convertors_available() {
registry.defineDocStringType(new DocStringType(
JsonNode.class,
"json",
(String s) -> new ObjectMapper().readTree(s)));
registry.defineDocStringType(jsonNodeForJson);

registry.defineDocStringType(new DocStringType(
JsonNode.class,
"xml",
(String s) -> new ObjectMapper().readTree(s)));
registry.defineDocStringType(jsonNodeForXml);

DocString docString = DocString.create(
"{\"hello\":\"world\"}");
Expand All @@ -211,20 +213,9 @@ void throws_when_multiple_convertors_available() {

@Test
void different_docstring_content_types_convert_to_matching_doc_string_types() {
registry.defineDocStringType(new DocStringType(
String.class,
"json",
(String s) -> s));

registry.defineDocStringType(new DocStringType(
String.class,
"xml",
(String s) -> s));

registry.defineDocStringType(new DocStringType(
String.class,
"yml",
(String s) -> s));
registry.defineDocStringType(stringForJson);
registry.defineDocStringType(stringForXml);
registry.defineDocStringType(stringForYaml);

DocString docStringJson = DocString.create(
"{\"content\":\"hello world\"}", "json");
Expand All @@ -237,9 +228,11 @@ void different_docstring_content_types_convert_to_matching_doc_string_types() {
String convertXml = converter.convert(docStringXml, String.class);
String convertYml = converter.convert(docStringYml, String.class);

assertThat(docStringJson.getContent(), equalTo(convertJson));
assertThat(docStringXml.getContent(), equalTo(convertXml));
assertThat(docStringYml.getContent(), equalTo(convertYml));
assertAll(
() -> assertThat(docStringJson.getContent(), equalTo(convertJson)),
() -> assertThat(docStringXml.getContent(), equalTo(convertXml)),
() -> assertThat(docStringYml.getContent(), equalTo(convertYml))
);
}

@Test
Expand Down
14 changes: 11 additions & 3 deletions java/src/main/java/io/cucumber/java/DocStringType.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@
/**
* Register doc string type.
* <p>
* The name of the method is used as the content type of the
* {@link io.cucumber.docstring.DocStringType}.
* <p>
* The method must have this signature:
* <ul>
* <li>{@code String -> Author}</li>
* </ul>
* NOTE: {@code Author} is an example of the type of the parameter type.
* <p>
* TODO: Explain how docstring types are selected.
* TODO: Explain anonymous docstring type
* TODO: Explain existence of default converter
* First by content type and target type.
* Then by target type.
*
*
* NOTE: When not provided the name of the method is used as the content type of the {@link io.cucumber.docstring.DocStringType}.
*
*
*
* @see io.cucumber.docstring.DocStringType
*/
Expand Down

0 comments on commit d8b4036

Please sign in to comment.