Skip to content

Commit c57e3da

Browse files
committed
test: improve gherkin test suite only relying on the newest version, with data loading
Signed-off-by: Simon Schrottner <[email protected]> diff --git c/src/test/java/dev/openfeature/sdk/e2e/steps/ContextSteps.java i/src/test/java/dev/openfeature/sdk/e2e/steps/ContextSteps.java index e4cd603..121b567 100644 --- c/src/test/java/dev/openfeature/sdk/e2e/steps/ContextSteps.java +++ i/src/test/java/dev/openfeature/sdk/e2e/steps/ContextSteps.java @@ -114,9 +114,9 @@ public class ContextSteps { public void a_context_containing_a_key_with_type_and_with_value(String key, String type, String value) throws ClassNotFoundException, InstantiationException { Map<String, Value> map = state.context.asMap(); - Map<String, Value> map = state.context.asMap(); map.put(key, new Value(Utils.convert(value, type))); state.context = new MutableContext(state.context.getTargetingKey(), map); + } @given("a context containing a targeting key with value {string}") public void a_context_containing_a_targeting_key_with_value(String string) { diff --git c/src/test/java/dev/openfeature/sdk/testutils/jackson/CelContextEvaluator.java i/src/test/java/dev/openfeature/sdk/testutils/jackson/CelContextEvaluator.java index 20f3f5f..138c23f 100644 --- c/src/test/java/dev/openfeature/sdk/testutils/jackson/CelContextEvaluator.java +++ i/src/test/java/dev/openfeature/sdk/testutils/jackson/CelContextEvaluator.java @@ -46,7 +46,6 @@ public class CelContextEvaluator<T> implements ContextEvaluator<T> { // Evaluate with context, overriding defaults. objectMap.putAll(evaluationContext.asObjectMap()); } - } Object result = program.eval(objectMap); diff --git c/src/test/java/dev/openfeature/sdk/testutils/jackson/VariantsMapDeserializer.java i/src/test/java/dev/openfeature/sdk/testutils/jackson/VariantsMapDeserializer.java index 339d8c8..9a63f58 100644 --- c/src/test/java/dev/openfeature/sdk/testutils/jackson/VariantsMapDeserializer.java +++ i/src/test/java/dev/openfeature/sdk/testutils/jackson/VariantsMapDeserializer.java @@ -50,6 +50,7 @@ public class VariantsMapDeserializer extends JsonDeserializer<Map<String, Object } private Object convertJsonNodeToValue(JsonNode node) throws InstantiationException { + if (node.isNull()) { return null; } else if (node.isBoolean()) { @@ -60,25 +61,8 @@ public class VariantsMapDeserializer extends JsonDeserializer<Map<String, Object return node.asDouble(); } else if (node.isTextual()) { return node.asText(); - } else if (node.isArray()) { - List<Object> list = new ArrayList<>(); - for (JsonNode item : node) { - list.add(convertJsonNodeToValue(item)); - } - return list; } else if (node.isObject()) { - Map<String, Value> map = new HashMap<>(); - Iterator<Map.Entry<String, JsonNode>> fields = node.fields(); - while (fields.hasNext()) { - Map.Entry<String, JsonNode> field = fields.next(); - Object o = convertJsonNodeToValue(field.getValue()); - if (o instanceof Value) { - map.put(field.getKey(), (Value) o); - } else { - map.put(field.getKey(), new Value(o)); - } - } - return new Value(new MutableStructure(map)); + return Value.objectToValue(node); } throw new IllegalArgumentException("Unsupported JSON node type: " + node.getNodeType()); Signed-off-by: Simon Schrottner <[email protected]>
1 parent 04e3230 commit c57e3da

File tree

9 files changed

+77
-58
lines changed

9 files changed

+77
-58
lines changed

pom.xml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,21 @@
168168
<scope>test</scope>
169169
</dependency>
170170

171+
<dependency>
172+
<groupId>com.fasterxml.jackson.core</groupId>
173+
<artifactId>jackson-core</artifactId>
174+
<scope>test</scope>
175+
</dependency>
176+
177+
<dependency>
178+
<groupId>com.fasterxml.jackson.core</groupId>
179+
<artifactId>jackson-annotations</artifactId>
180+
<scope>test</scope>
181+
</dependency>
182+
171183
<dependency>
172184
<groupId>com.fasterxml.jackson.core</groupId>
173185
<artifactId>jackson-databind</artifactId>
174-
<version>2.19.2</version>
175186
<scope>test</scope>
176187
</dependency>
177188

@@ -205,6 +216,14 @@
205216
</dependency>
206217
<!-- End mockito workaround-->
207218

219+
<dependency>
220+
<groupId>com.fasterxml.jackson</groupId>
221+
<artifactId>jackson-bom</artifactId>
222+
<version>2.16.1</version> <!-- Use the desired version -->
223+
<type>pom</type>
224+
<scope>import</scope>
225+
</dependency>
226+
208227
<dependency>
209228
<groupId>io.cucumber</groupId>
210229
<artifactId>cucumber-bom</artifactId>

src/test/java/dev/openfeature/sdk/e2e/GherkinSpecTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
1717
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.sdk.e2e.steps")
1818
@ConfigurationParameter(key = OBJECT_FACTORY_PROPERTY_NAME, value = "io.cucumber.picocontainer.PicoFactory")
19-
@ExcludeTags({"deprecated"})
19+
@ExcludeTags({"deprecated", "provider-status", "reason-codes", "async", "immutability", "evaluation-options"})
2020
public class GherkinSpecTest {}

src/test/java/dev/openfeature/sdk/e2e/Utils.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package dev.openfeature.sdk.e2e;
22

3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import dev.openfeature.sdk.Value;
36
import java.util.Objects;
47

58
public final class Utils {
@@ -22,6 +25,12 @@ public static Object convert(String value, String type) {
2225
return Double.parseDouble(value);
2326
case "long":
2427
return Long.parseLong(value);
28+
case "object":
29+
try {
30+
return Value.objectToValue(new ObjectMapper().readValue(value, Object.class));
31+
} catch (JsonProcessingException e) {
32+
throw new RuntimeException(e);
33+
}
2534
}
2635
throw new RuntimeException("Unknown config type: " + type);
2736
}

src/test/java/dev/openfeature/sdk/e2e/steps/ContextSteps.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import dev.openfeature.sdk.Value;
1616
import dev.openfeature.sdk.e2e.ContextStoringProvider;
1717
import dev.openfeature.sdk.e2e.State;
18+
import dev.openfeature.sdk.e2e.Utils;
1819
import io.cucumber.datatable.DataTable;
1920
import io.cucumber.java.en.And;
2021
import io.cucumber.java.en.Given;
@@ -105,18 +106,16 @@ public void contextEntriesForEachLevelFromAPILevelDownToTheLevelWithKeyAndValue(
105106
}
106107

107108
@Given("a context containing a key {string} with null value")
108-
public void a_context_containing_a_key_with_null_value(String key)
109-
throws ClassNotFoundException, InstantiationException {
109+
public void a_context_containing_a_key_with_null_value(String key) {
110110
a_context_containing_a_key_with_type_and_with_value(key, "String", null);
111111
}
112112

113113
@Given("a context containing a key {string}, with type {string} and with value {string}")
114-
public void a_context_containing_a_key_with_type_and_with_value(String key, String type, String value)
115-
throws ClassNotFoundException, InstantiationException {
114+
public void a_context_containing_a_key_with_type_and_with_value(String key, String type, String value) {
116115
Map<String, Value> map = state.context.asMap();
117-
Map<String, Value> map = state.context.asMap();
118-
map.put(key, new Value(Utils.convert(value, type)));
116+
map.put(key, Value.objectToValue(Utils.convert(value, type)));
119117
state.context = new MutableContext(state.context.getTargetingKey(), map);
118+
}
120119

121120
@Given("a context containing a targeting key with value {string}")
122121
public void a_context_containing_a_targeting_key_with_value(String string) {

src/test/java/dev/openfeature/sdk/e2e/steps/FlagStepDefinitions.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,15 @@ public void the_flag_was_evaluated_with_details() {
6161

6262
@Then("the resolved details value should be {string}")
6363
public void the_resolved_details_value_should_be(String value) {
64-
assertThat(state.evaluation.getValue()).isEqualTo(Utils.convert(value, state.flag.type));
64+
Object evaluationValue = state.evaluation.getValue();
65+
if (state.flag.type.equalsIgnoreCase("object")) {
66+
assertThat(((Value) evaluationValue).asStructure().asObjectMap())
67+
.isEqualTo(((Value) Utils.convert(value, state.flag.type))
68+
.asStructure()
69+
.asObjectMap());
70+
} else {
71+
assertThat(evaluationValue).isEqualTo(Utils.convert(value, state.flag.type));
72+
}
6573
}
6674

6775
@Then("the flag key should be {string}")

src/test/java/dev/openfeature/sdk/testutils/TestFlagsUtils.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import dev.openfeature.sdk.testutils.jackson.InMemoryFlagMixin;
1313
import java.io.IOException;
1414
import java.nio.file.Paths;
15+
import java.util.Collections;
1516
import java.util.Map;
1617
import lombok.experimental.UtilityClass;
1718
import lombok.extern.slf4j.Slf4j;
@@ -32,33 +33,37 @@ public class TestFlagsUtils {
3233
public static final String WRONG_FLAG_KEY = "wrong-flag";
3334
public static final String METADATA_FLAG_KEY = "metadata-flag";
3435

36+
private static Map<String, Flag<?>> flags;
3537
/**
3638
* Building flags for testing purposes.
3739
*
3840
* @return map of flags
3941
*/
4042
public static Map<String, Flag<?>> buildFlags() {
41-
ObjectMapper objectMapper = new ObjectMapper();
42-
objectMapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);
43-
objectMapper.addMixIn(Flag.class, InMemoryFlagMixin.class);
44-
objectMapper.addMixIn(Flag.FlagBuilder.class, InMemoryFlagMixin.FlagBuilderMixin.class);
43+
if (flags == null) {
44+
ObjectMapper objectMapper = new ObjectMapper();
45+
objectMapper.configure(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION.mappedFeature(), true);
46+
objectMapper.addMixIn(Flag.class, InMemoryFlagMixin.class);
47+
objectMapper.addMixIn(Flag.FlagBuilder.class, InMemoryFlagMixin.FlagBuilderMixin.class);
4548

46-
SimpleModule module = new SimpleModule();
47-
module.addDeserializer(ImmutableMetadata.class, new ImmutableMetadataDeserializer());
48-
module.addDeserializer(ContextEvaluator.class, new ContextEvaluatorDeserializer());
49-
objectMapper.registerModule(module);
49+
SimpleModule module = new SimpleModule();
50+
module.addDeserializer(ImmutableMetadata.class, new ImmutableMetadataDeserializer());
51+
module.addDeserializer(ContextEvaluator.class, new ContextEvaluatorDeserializer());
52+
objectMapper.registerModule(module);
5053

51-
Map<String, Flag<?>> flagsJson;
52-
try {
53-
flagsJson = objectMapper.readValue(
54-
Paths.get("spec/specification/assets/gherkin/test-flags.json")
55-
.toFile(),
56-
new TypeReference<>() {});
54+
Map<String, Flag<?>> flagsJson;
55+
try {
56+
flagsJson = objectMapper.readValue(
57+
Paths.get("spec/specification/assets/gherkin/test-flags.json")
58+
.toFile(),
59+
new TypeReference<>() {});
5760

58-
} catch (IOException e) {
59-
throw new RuntimeException(e);
61+
} catch (IOException e) {
62+
throw new RuntimeException(e);
63+
}
64+
flags = Collections.unmodifiableMap(flagsJson);
6065
}
6166

62-
return flagsJson;
67+
return flags;
6368
}
6469
}

src/test/java/dev/openfeature/sdk/testutils/jackson/CelContextEvaluator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public CelContextEvaluator(String expression) {
1919
CelRuntime celRuntime =
2020
CelRuntimeFactory.standardCelRuntimeBuilder().build();
2121
CelCompiler celCompiler = CelCompilerFactory.standardCelCompilerBuilder()
22-
.addVar("customer", SimpleType.STRING)
22+
.addVar("customer", SimpleType.BOOL)
2323
.addVar("email", SimpleType.STRING)
2424
.addVar("dummy", SimpleType.STRING)
2525
.setResultType(SimpleType.STRING)
@@ -36,6 +36,7 @@ public CelContextEvaluator(String expression) {
3636
@Override
3737
@SuppressWarnings("unchecked")
3838
public T evaluate(Flag flag, EvaluationContext evaluationContext) {
39+
try {
3940
Map<String, Object> objectMap = new HashMap<>();
4041
// Provide defaults for all declared variables to prevent runtime errors.
4142
objectMap.put("email", "");
@@ -46,7 +47,6 @@ public T evaluate(Flag flag, EvaluationContext evaluationContext) {
4647
// Evaluate with context, overriding defaults.
4748
objectMap.putAll(evaluationContext.asObjectMap());
4849
}
49-
}
5050

5151
Object result = program.eval(objectMap);
5252

src/test/java/dev/openfeature/sdk/testutils/jackson/VariantsMapDeserializer.java

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package dev.openfeature.sdk.testutils.jackson;
22

33
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
45
import com.fasterxml.jackson.databind.DeserializationContext;
56
import com.fasterxml.jackson.databind.JsonDeserializer;
67
import com.fasterxml.jackson.databind.JsonNode;
7-
import dev.openfeature.sdk.MutableStructure;
88
import dev.openfeature.sdk.Value;
99
import java.io.IOException;
10-
import java.util.ArrayList;
1110
import java.util.HashMap;
1211
import java.util.Iterator;
1312
import java.util.List;
@@ -27,29 +26,24 @@ public Map<String, Object> deserialize(JsonParser p, DeserializationContext ctxt
2726
JsonNode variantNode = field.getValue();
2827

2928
// Convert the variant value to OpenFeature Value
30-
Object variantValue = null;
31-
try {
32-
variantValue = convertToValue(variantNode);
33-
} catch (InstantiationException e) {
34-
throw new RuntimeException(e);
35-
}
29+
Object variantValue = convertToValue(p, variantNode);
3630
variants.put(variantKey, variantValue);
3731
}
3832

3933
return variants;
4034
}
4135

42-
private Object convertToValue(JsonNode node) throws InstantiationException {
36+
private Object convertToValue(JsonParser p, JsonNode node) throws JsonProcessingException {
4337
// If the node has a "value" property, use that
4438
if (node.isObject() && node.has("value")) {
45-
return convertJsonNodeToValue(node.get("value"));
39+
return convertJsonNodeToValue(p, node.get("value"));
4640
}
4741

4842
// Otherwise, treat the entire node as the value
49-
return convertJsonNodeToValue(node);
43+
return convertJsonNodeToValue(p, node);
5044
}
5145

52-
private Object convertJsonNodeToValue(JsonNode node) throws InstantiationException {
46+
private Object convertJsonNodeToValue(JsonParser p, JsonNode node) throws JsonProcessingException {
5347
if (node.isNull()) {
5448
return null;
5549
} else if (node.isBoolean()) {
@@ -61,24 +55,9 @@ private Object convertJsonNodeToValue(JsonNode node) throws InstantiationExcepti
6155
} else if (node.isTextual()) {
6256
return node.asText();
6357
} else if (node.isArray()) {
64-
List<Object> list = new ArrayList<>();
65-
for (JsonNode item : node) {
66-
list.add(convertJsonNodeToValue(item));
67-
}
68-
return list;
58+
return Value.objectToValue(p.getCodec().treeToValue(node, List.class));
6959
} else if (node.isObject()) {
70-
Map<String, Value> map = new HashMap<>();
71-
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
72-
while (fields.hasNext()) {
73-
Map.Entry<String, JsonNode> field = fields.next();
74-
Object o = convertJsonNodeToValue(field.getValue());
75-
if (o instanceof Value) {
76-
map.put(field.getKey(), (Value) o);
77-
} else {
78-
map.put(field.getKey(), new Value(o));
79-
}
80-
}
81-
return new Value(new MutableStructure(map));
60+
return Value.objectToValue(p.getCodec().treeToValue(node, Object.class));
8261
}
8362

8463
throw new IllegalArgumentException("Unsupported JSON node type: " + node.getNodeType());

0 commit comments

Comments
 (0)