Skip to content

Commit cac1a53

Browse files
committed
[Core] Look up docstring converter by type as fallback
Fixes: #2458
1 parent 0364976 commit cac1a53

File tree

6 files changed

+80
-19
lines changed

6 files changed

+80
-19
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1616
### Removed
1717

1818
### Fixed
19+
* [Core] Look up docstring converter by type as fallback ([#2459](https://github.com/cucumber/cucumber-jvm/pull/2459) M.P. Korstanje)
1920

2021
## [7.2.1] (2022-01-04)
2122

core/src/main/java/io/cucumber/core/stepexpression/DocStringArgument.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22

33
import io.cucumber.docstring.DocString;
44

5+
import static java.util.Objects.requireNonNull;
6+
57
public final class DocStringArgument implements Argument {
68

79
private final DocStringTransformer<?> docStringType;
810
private final String content;
911
private final String contentType;
1012

1113
DocStringArgument(DocStringTransformer<?> docStringType, String content, String contentType) {
12-
this.docStringType = docStringType;
13-
this.content = content;
14+
this.docStringType = requireNonNull(docStringType);
15+
this.content = requireNonNull(content);
1416
this.contentType = contentType;
1517
}
1618

core/src/main/java/io/cucumber/core/stepexpression/StepExpression.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
import java.util.ArrayList;
77
import java.util.List;
88

9+
import static java.util.Objects.requireNonNull;
10+
911
public final class StepExpression {
1012

1113
private final Expression expression;
1214
private final DocStringTransformer<?> docStringType;
1315
private final RawTableTransformer<?> tableType;
1416

1517
StepExpression(Expression expression, DocStringTransformer<?> docStringType, RawTableTransformer<?> tableType) {
16-
this.expression = expression;
17-
this.docStringType = docStringType;
18-
this.tableType = tableType;
18+
this.expression = requireNonNull(expression);
19+
this.docStringType = requireNonNull(docStringType);
20+
this.tableType = requireNonNull(tableType);
1921
}
2022

2123
public Class<? extends Expression> getExpressionType() {

docstring/src/main/java/io/cucumber/docstring/DocStringTypeRegistry.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,16 @@ private static String emptyToAnonymous(String contentType) {
5151
}
5252

5353
List<DocStringType> lookup(String contentType, Type type) {
54-
if (contentType == null) {
55-
return lookUpByType(type);
54+
DocStringType docStringType = lookupByContentTypeAndType(orDefault(contentType), type);
55+
if (docStringType != null) {
56+
return Collections.singletonList(docStringType);
5657
}
5758

58-
DocStringType docStringType = lookupByContentTypeAndType(contentType, type);
59-
if (docStringType == null) {
60-
return Collections.emptyList();
61-
}
62-
return Collections.singletonList(docStringType);
59+
return lookUpByType(type);
60+
}
61+
62+
private String orDefault(String contentType) {
63+
return contentType == null ? DEFAULT_CONTENT_TYPE : contentType;
6364
}
6465

6566
private List<DocStringType> lookUpByType(Type type) {

docstring/src/main/java/io/cucumber/docstring/DocStringTypeRegistryDocStringConverter.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,19 @@ public <T> T convert(DocString docString, Type targetType) {
3939
targetType.getTypeName()));
4040
}
4141
if (docStringTypes.size() > 1) {
42+
List<String> suggestedContentTypes = suggestedContentTypes(docStringTypes);
43+
if (docString.getContentType() == null) {
44+
throw new CucumberDocStringException(format(
45+
"Multiple converters found for type %s, add one of the following content types to your docstring %s",
46+
targetType.getTypeName(),
47+
suggestedContentTypes));
48+
}
4249
throw new CucumberDocStringException(format(
43-
"Multiple converters found for type %s, add one of the following content types to your docstring %s",
50+
"Multiple converters found for type %s, and the content type '%s' did not match any of the registered types %s. Change the content type of the docstring or register a docstring type for '%s'",
4451
targetType.getTypeName(),
45-
suggestedContentTypes(docStringTypes)));
52+
docString.getContentType(),
53+
suggestedContentTypes,
54+
docString.getContentType()));
4655
}
4756

4857
return (T) docStringTypes.get(0).transform(docString.getContent());

docstring/src/test/java/io/cucumber/docstring/DocStringTypeRegistryDocStringConverterTest.java

+51-5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,57 @@ void target_type_to_string_is_predefined() {
6060
assertThat(converted, is("hello world"));
6161
}
6262

63+
@Test
64+
void default_converter_is_used_if_registered_converter_does_not_match_type() {
65+
registry.defineDocStringType(new DocStringType(
66+
JsonNode.class,
67+
"json",
68+
(String s) -> new ObjectMapper().readTree(s)));
69+
70+
DocString docString = DocString.create(
71+
"hello world", "json");
72+
73+
String converted = converter.convert(docString, String.class);
74+
assertThat(converted, is("hello world"));
75+
}
76+
77+
@Test
78+
void default_converter_never_conflicts_with_registered_converter_for_string() {
79+
registry.defineDocStringType(new DocStringType(
80+
String.class,
81+
"text",
82+
(String s) -> s));
83+
84+
DocString docString = DocString.create("hello world");
85+
86+
String converted = converter.convert(docString, String.class);
87+
assertThat(converted, is("hello world"));
88+
}
89+
90+
@Test
91+
void throws_if_converter_type_conflicts_with_type() {
92+
registry.defineDocStringType(new DocStringType(
93+
JsonNode.class,
94+
"json",
95+
(String s) -> new ObjectMapper().readTree(s)));
96+
97+
registry.defineDocStringType(new DocStringType(
98+
String.class,
99+
"text",
100+
(String s) -> s));
101+
102+
DocString docString = DocString.create("hello world", "json");
103+
104+
CucumberDocStringException exception = assertThrows(
105+
CucumberDocStringException.class,
106+
() -> converter.convert(docString, String.class));
107+
108+
assertThat(exception.getMessage(),
109+
is("Multiple converters found for type java.lang.String, and the content type 'json' " +
110+
"did not match any of the registered types [text]. Change the content type of the docstring " +
111+
"or register a docstring type for 'json'"));
112+
}
113+
63114
@Test
64115
void converts_doc_string_to_doc_string() {
65116
DocString docString = DocString.create(
@@ -146,11 +197,6 @@ void throws_when_multiple_convertors_available() {
146197
"xml",
147198
(String s) -> new ObjectMapper().readTree(s)));
148199

149-
registry.defineDocStringType(new DocStringType(
150-
JsonNode.class,
151-
"",
152-
(String s) -> new ObjectMapper().readTree(s)));
153-
154200
DocString docString = DocString.create(
155201
"{\"hello\":\"world\"}");
156202

0 commit comments

Comments
 (0)