From 154a1b90972323d24a0f3d6e5762c0fc36c1a3a1 Mon Sep 17 00:00:00 2001 From: "christian.lutnik" Date: Mon, 10 Feb 2025 16:26:29 +0100 Subject: [PATCH 1/5] feat: implement gherkin tests Signed-off-by: christian.lutnik --- pom.xml | 21 +--- .../openfeature/sdk/ImmutableMetadata.java | 4 + .../openfeature/sdk/OpenFeatureClient.java | 2 +- .../sdk/providers/memory/Flag.java | 2 + .../providers/memory/InMemoryProvider.java | 1 + .../openfeature/sdk/e2e/EvaluationTest.java | 8 +- .../java/dev/openfeature/sdk/e2e/Flag.java | 13 +++ .../dev/openfeature/sdk/e2e/MockHook.java | 46 ++++++++ .../java/dev/openfeature/sdk/e2e/State.java | 13 +++ .../java/dev/openfeature/sdk/e2e/Utils.java | 28 +++++ .../sdk/e2e/steps/FlagStepDefinitions.java | 104 ++++++++++++++++++ .../openfeature/sdk/e2e/steps/HookSteps.java | 84 ++++++++++++++ .../sdk/e2e/steps/ProviderSteps.java | 26 +++++ .../StepDefinitions.java | 2 +- .../sdk/testutils/TestFlagsUtils.java | 16 +++ 15 files changed, 350 insertions(+), 20 deletions(-) create mode 100644 src/test/java/dev/openfeature/sdk/e2e/Flag.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/MockHook.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/State.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/Utils.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/steps/FlagStepDefinitions.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java create mode 100644 src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java rename src/test/java/dev/openfeature/sdk/e2e/{evaluation => steps}/StepDefinitions.java (99%) diff --git a/pom.xml b/pom.xml index 8b3ce85af..5e1635017 100644 --- a/pom.xml +++ b/pom.xml @@ -128,6 +128,12 @@ test + + io.cucumber + cucumber-picocontainer + test + + org.simplify4u slf4j2-mock @@ -608,21 +614,6 @@ - - copy-evaluation-gherkin-tests - validate - - exec - - - - cp - - spec/specification/assets/gherkin/evaluation.feature - src/test/resources/features/ - - - diff --git a/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java b/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java index c2b6f5838..f8311a9a5 100644 --- a/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java +++ b/src/main/java/dev/openfeature/sdk/ImmutableMetadata.java @@ -97,6 +97,10 @@ public T getValue(final String key, final Class type) { } } + public boolean isEmpty() { + return metadata.isEmpty(); + } + /** * Obtain a builder for {@link ImmutableMetadata}. */ diff --git a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java index 66f25f60a..1c11bbb5c 100644 --- a/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java +++ b/src/main/java/dev/openfeature/sdk/OpenFeatureClient.java @@ -217,7 +217,7 @@ private FlagEvaluationDetails evaluateFlag( } } catch (Exception e) { if (details == null) { - details = FlagEvaluationDetails.builder().build(); + details = FlagEvaluationDetails.builder().flagKey(key).build(); } if (e instanceof OpenFeatureError) { details.setErrorCode(((OpenFeatureError) e).getErrorCode()); diff --git a/src/main/java/dev/openfeature/sdk/providers/memory/Flag.java b/src/main/java/dev/openfeature/sdk/providers/memory/Flag.java index 61778d85b..f2dc6b495 100644 --- a/src/main/java/dev/openfeature/sdk/providers/memory/Flag.java +++ b/src/main/java/dev/openfeature/sdk/providers/memory/Flag.java @@ -1,5 +1,6 @@ package dev.openfeature.sdk.providers.memory; +import dev.openfeature.sdk.ImmutableMetadata; import java.util.Map; import lombok.Builder; import lombok.Getter; @@ -18,4 +19,5 @@ public class Flag { private String defaultVariant; private ContextEvaluator contextEvaluator; + private ImmutableMetadata flagMetadata; } diff --git a/src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java b/src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java index d3fdb985c..3be1b6316 100644 --- a/src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java +++ b/src/main/java/dev/openfeature/sdk/providers/memory/InMemoryProvider.java @@ -152,6 +152,7 @@ private ProviderEvaluation getEvaluation( .value(value) .variant(flag.getDefaultVariant()) .reason(Reason.STATIC.toString()) + .flagMetadata(flag.getFlagMetadata()) .build(); } } diff --git a/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java b/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java index 8a3381412..b7c834312 100644 --- a/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java +++ b/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java @@ -1,16 +1,18 @@ package dev.openfeature.sdk.e2e; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; +import static io.cucumber.junit.platform.engine.Constants.OBJECT_FACTORY_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME; import org.junit.platform.suite.api.ConfigurationParameter; import org.junit.platform.suite.api.IncludeEngines; -import org.junit.platform.suite.api.SelectClasspathResource; +import org.junit.platform.suite.api.SelectDirectories; import org.junit.platform.suite.api.Suite; @Suite @IncludeEngines("cucumber") -@SelectClasspathResource("features/evaluation.feature") +@SelectDirectories("spec/specification/assets/gherkin") @ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty") -@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.sdk.e2e.evaluation") +@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.sdk.e2e.steps") +@ConfigurationParameter(key = OBJECT_FACTORY_PROPERTY_NAME, value = "io.cucumber.picocontainer.PicoFactory") public class EvaluationTest {} diff --git a/src/test/java/dev/openfeature/sdk/e2e/Flag.java b/src/test/java/dev/openfeature/sdk/e2e/Flag.java new file mode 100644 index 000000000..2c4ffdb57 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/Flag.java @@ -0,0 +1,13 @@ +package dev.openfeature.sdk.e2e; + +public class Flag { + public String name; + public Object defaultValue; + public String type; + + public Flag(String type, String name, Object defaultValue) { + this.name = name; + this.defaultValue = defaultValue; + this.type = type; + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/MockHook.java b/src/test/java/dev/openfeature/sdk/e2e/MockHook.java new file mode 100644 index 000000000..5954f871c --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/MockHook.java @@ -0,0 +1,46 @@ +package dev.openfeature.sdk.e2e; + +import dev.openfeature.sdk.EvaluationContext; +import dev.openfeature.sdk.FlagEvaluationDetails; +import dev.openfeature.sdk.Hook; +import dev.openfeature.sdk.HookContext; +import lombok.Getter; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class MockHook implements Hook { + @Getter + private boolean beforeCalled; + @Getter + private boolean afterCalled; + @Getter + private boolean errorCalled; + @Getter + private boolean finallyAfterCalled; + @Getter + private final Map evaluationDetails = new HashMap<>(); + + @Override + public Optional before(HookContext ctx, Map hints) { + beforeCalled = true; + return Optional.of(ctx.getCtx()); + } + + @Override + public void after(HookContext ctx, FlagEvaluationDetails details, Map hints) { + afterCalled = true; + evaluationDetails.put("after", details); + } + + @Override + public void error(HookContext ctx, Exception error, Map hints) { + errorCalled = true; + } + + @Override + public void finallyAfter(HookContext ctx, FlagEvaluationDetails details, Map hints) { + finallyAfterCalled = true; + evaluationDetails.put("finally", details); + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/State.java b/src/test/java/dev/openfeature/sdk/e2e/State.java new file mode 100644 index 000000000..ee513b00e --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/State.java @@ -0,0 +1,13 @@ +package dev.openfeature.sdk.e2e; + +import dev.openfeature.sdk.Client; +import dev.openfeature.sdk.FlagEvaluationDetails; +import dev.openfeature.sdk.MutableContext; + +public class State { + public Client client; + public Flag flag; + public MutableContext context = new MutableContext(); + public FlagEvaluationDetails evaluation; + public MockHook hook; +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/Utils.java b/src/test/java/dev/openfeature/sdk/e2e/Utils.java new file mode 100644 index 000000000..902ee11d0 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/Utils.java @@ -0,0 +1,28 @@ +package dev.openfeature.sdk.e2e; + +import java.util.Objects; + +public final class Utils { + + private Utils() {} + + public static Object convert(String value, String type) { + if (Objects.equals(value, "null")) { + return null; + } + switch (type.toLowerCase()) { + case "boolean": + return Boolean.parseBoolean(value); + case "string": + return value; + case "integer": + return Integer.parseInt(value); + case "float": + case "double": + return Double.parseDouble(value); + case "long": + return Long.parseLong(value); + } + throw new RuntimeException("Unknown config type: " + type); + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/steps/FlagStepDefinitions.java b/src/test/java/dev/openfeature/sdk/e2e/steps/FlagStepDefinitions.java new file mode 100644 index 000000000..390e067f3 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/steps/FlagStepDefinitions.java @@ -0,0 +1,104 @@ +package dev.openfeature.sdk.e2e.steps; + +import static org.assertj.core.api.Assertions.assertThat; + +import dev.openfeature.sdk.FlagEvaluationDetails; +import dev.openfeature.sdk.ImmutableMetadata; +import dev.openfeature.sdk.Value; +import dev.openfeature.sdk.e2e.Flag; +import dev.openfeature.sdk.e2e.State; +import dev.openfeature.sdk.e2e.Utils; +import io.cucumber.datatable.DataTable; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; + +public class FlagStepDefinitions { + private final State state; + + public FlagStepDefinitions(State state) { + this.state = state; + } + + @Given("a {}-flag with key {string} and a default value {string}") + public void givenAFlag(String type, String name, String defaultValue) { + state.flag = new Flag(type, name, Utils.convert(defaultValue, type)); + } + + @When("the flag was evaluated with details") + public void the_flag_was_evaluated_with_details() { + FlagEvaluationDetails details; + switch (state.flag.type.toLowerCase()) { + case "string": + details = + state.client.getStringDetails(state.flag.name, (String) state.flag.defaultValue, state.context); + break; + case "boolean": + details = state.client.getBooleanDetails( + state.flag.name, (Boolean) state.flag.defaultValue, state.context); + break; + case "float": + details = + state.client.getDoubleDetails(state.flag.name, (Double) state.flag.defaultValue, state.context); + break; + case "integer": + details = state.client.getIntegerDetails( + state.flag.name, (Integer) state.flag.defaultValue, state.context); + break; + case "object": + details = + state.client.getObjectDetails(state.flag.name, (Value) state.flag.defaultValue, state.context); + break; + default: + throw new AssertionError(); + } + state.evaluation = details; + } + + @Then("the resolved details value should be {string}") + public void the_resolved_details_value_should_be(String value) { + assertThat(state.evaluation.getValue()).isEqualTo(Utils.convert(value, state.flag.type)); + } + + @Then("the reason should be {string}") + public void the_reason_should_be(String reason) { + assertThat(state.evaluation.getReason()).isEqualTo(reason); + } + + @Then("the variant should be {string}") + public void the_variant_should_be(String variant) { + assertThat(state.evaluation.getVariant()).isEqualTo(variant); + } + + @Then("the resolved metadata value \"{}\" with type \"{}\" should be \"{}\"") + public void theResolvedMetadataValueShouldBe(String key, String type, String value) + throws NoSuchFieldException, IllegalAccessException { + Field f = state.evaluation.getFlagMetadata().getClass().getDeclaredField("metadata"); + f.setAccessible(true); + HashMap metadata = (HashMap) f.get(state.evaluation.getFlagMetadata()); + assertThat(metadata).containsEntry(key, Utils.convert(value, type)); + } + + @Then("the resolved metadata is empty") + public void theResolvedMetadataIsEmpty() { + assertThat(state.evaluation.getFlagMetadata().isEmpty()).isTrue(); + } + + @Then("the resolved metadata should contain") + public void theResolvedMetadataShouldContain(DataTable dataTable) { + ImmutableMetadata evaluationMetadata = state.evaluation.getFlagMetadata(); + List> asLists = dataTable.asLists(); + for (int i = 1; i < asLists.size(); i++) { // skip the header of the table + List line = asLists.get(i); + String key = line.get(0); + String metadataType = line.get(1); + Object value = Utils.convert(line.get(2), metadataType); + + assertThat(value).isNotNull(); + assertThat(evaluationMetadata.getValue(key, value.getClass())).isEqualTo(value); + } + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java b/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java new file mode 100644 index 000000000..5e4d290b0 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java @@ -0,0 +1,84 @@ +package dev.openfeature.sdk.e2e.steps; + +import dev.openfeature.sdk.FlagEvaluationDetails; +import dev.openfeature.sdk.e2e.MockHook; +import dev.openfeature.sdk.e2e.State; +import dev.openfeature.sdk.e2e.Utils; +import io.cucumber.datatable.DataTable; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; + +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class HookSteps { + private final State state; + + public HookSteps(State state) { + this.state = state; + } + + @Given("a client with added hook") + public void aClientWithAddedHook() { + MockHook hook = new MockHook(); + state.hook = hook; + state.client.addHooks(hook); + } + + @Then("the {string} hook should have been executed") + public void theHookShouldHaveBeenExecuted(String hookName) { + assertHookCalled(hookName); + } + + public void assertHookCalled(String hookName) { + if ("before".equals(hookName)) { + assertTrue(state.hook.isBeforeCalled()); + } else if ("after".equals(hookName)) { + assertTrue(state.hook.isAfterCalled()); + } else if ("error".equals(hookName)) { + assertTrue(state.hook.isErrorCalled()); + } else if ("finally".equals(hookName)) { + assertTrue(state.hook.isFinallyAfterCalled()); + } else { + throw new IllegalArgumentException(hookName + " is not a valid hook name"); + } + } + + @And("the {string} hooks should be called with evaluation details") + public void theHooksShouldBeCalledWithEvaluationDetails(String hookNames, DataTable data) { + for (String hookName : hookNames.split(", ")) { + assertHookCalled(hookName); + FlagEvaluationDetails evaluationDetails = state.hook.getEvaluationDetails().get(hookName); + assertNotNull(evaluationDetails); + List> dataEntries = data.asMaps(); + for (Map line : dataEntries) { + String key = line.get("key"); + Object expected = Utils.convert(line.get("value"), line.get("data_type")); + Object actual; + if ("flag_key".equals(key)) { + actual = evaluationDetails.getFlagKey(); + } else if ("value".equals(key)) { + actual = evaluationDetails.getValue(); + } else if ("variant".equals(key)) { + actual = evaluationDetails.getVariant(); + } else if ("reason".equals(key)) { + actual = evaluationDetails.getReason(); + } else if ("error_code".equals(key)) { + actual = evaluationDetails.getErrorCode(); + if (actual != null) { + actual = actual.toString(); + } + } else { + throw new IllegalArgumentException(key + " is not a valid key"); + } + + assertEquals(expected, actual); + } + } + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java b/src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java new file mode 100644 index 000000000..82cdb2e79 --- /dev/null +++ b/src/test/java/dev/openfeature/sdk/e2e/steps/ProviderSteps.java @@ -0,0 +1,26 @@ +package dev.openfeature.sdk.e2e.steps; + +import static dev.openfeature.sdk.testutils.TestFlagsUtils.buildFlags; + +import dev.openfeature.sdk.OpenFeatureAPI; +import dev.openfeature.sdk.e2e.State; +import dev.openfeature.sdk.providers.memory.Flag; +import dev.openfeature.sdk.providers.memory.InMemoryProvider; +import io.cucumber.java.en.Given; +import java.util.Map; + +public class ProviderSteps { + private final State state; + + public ProviderSteps(State state) { + this.state = state; + } + + @Given("a stable provider") + public void aStableProvider() { + Map> flags = buildFlags(); + InMemoryProvider provider = new InMemoryProvider(flags); + OpenFeatureAPI.getInstance().setProviderAndWait(provider); + state.client = OpenFeatureAPI.getInstance().getClient(); + } +} diff --git a/src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java b/src/test/java/dev/openfeature/sdk/e2e/steps/StepDefinitions.java similarity index 99% rename from src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java rename to src/test/java/dev/openfeature/sdk/e2e/steps/StepDefinitions.java index c1e56429d..6897e2738 100644 --- a/src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java +++ b/src/test/java/dev/openfeature/sdk/e2e/steps/StepDefinitions.java @@ -1,4 +1,4 @@ -package dev.openfeature.sdk.e2e.evaluation; +package dev.openfeature.sdk.e2e.steps; import static dev.openfeature.sdk.testutils.TestFlagsUtils.buildFlags; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/dev/openfeature/sdk/testutils/TestFlagsUtils.java b/src/test/java/dev/openfeature/sdk/testutils/TestFlagsUtils.java index 157b07175..c1767ff6f 100644 --- a/src/test/java/dev/openfeature/sdk/testutils/TestFlagsUtils.java +++ b/src/test/java/dev/openfeature/sdk/testutils/TestFlagsUtils.java @@ -3,6 +3,7 @@ import static dev.openfeature.sdk.Structure.mapToStructure; import com.google.common.collect.ImmutableMap; +import dev.openfeature.sdk.ImmutableMetadata; import dev.openfeature.sdk.Value; import dev.openfeature.sdk.providers.memory.Flag; import java.util.HashMap; @@ -22,9 +23,11 @@ public class TestFlagsUtils { public static final String OBJECT_FLAG_KEY = "object-flag"; public static final String CONTEXT_AWARE_FLAG_KEY = "context-aware"; public static final String WRONG_FLAG_KEY = "wrong-flag"; + public static final String METADATA_FLAG_KEY = "metadata-flag"; /** * Building flags for testing purposes. + * * @return map of flags */ public static Map> buildFlags() { @@ -90,6 +93,19 @@ public static Map> buildFlags() { .variant("two", "dos") .defaultVariant("one") .build()); + flags.put( + METADATA_FLAG_KEY, + Flag.builder() + .variant("on", true) + .variant("off", false) + .defaultVariant("on") + .flagMetadata(ImmutableMetadata.builder() + .addString("string", "1.0.2") + .addInteger("integer", 2) + .addBoolean("boolean", true) + .addDouble("float", 0.1d) + .build()) + .build()); return flags; } } From c5b1cbed5951759319ea955ccb917fc80e50b87c Mon Sep 17 00:00:00 2001 From: "christian.lutnik" Date: Mon, 10 Feb 2025 16:35:02 +0100 Subject: [PATCH 2/5] fixup! feat: implement gherkin tests Signed-off-by: christian.lutnik --- src/test/java/dev/openfeature/sdk/e2e/MockHook.java | 6 +++++- .../dev/openfeature/sdk/e2e/steps/HookSteps.java | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/test/java/dev/openfeature/sdk/e2e/MockHook.java b/src/test/java/dev/openfeature/sdk/e2e/MockHook.java index 5954f871c..ac107cfd6 100644 --- a/src/test/java/dev/openfeature/sdk/e2e/MockHook.java +++ b/src/test/java/dev/openfeature/sdk/e2e/MockHook.java @@ -4,20 +4,24 @@ import dev.openfeature.sdk.FlagEvaluationDetails; import dev.openfeature.sdk.Hook; import dev.openfeature.sdk.HookContext; -import lombok.Getter; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import lombok.Getter; public class MockHook implements Hook { @Getter private boolean beforeCalled; + @Getter private boolean afterCalled; + @Getter private boolean errorCalled; + @Getter private boolean finallyAfterCalled; + @Getter private final Map evaluationDetails = new HashMap<>(); diff --git a/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java b/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java index 5e4d290b0..1e6a9172f 100644 --- a/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java +++ b/src/test/java/dev/openfeature/sdk/e2e/steps/HookSteps.java @@ -1,5 +1,9 @@ package dev.openfeature.sdk.e2e.steps; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + import dev.openfeature.sdk.FlagEvaluationDetails; import dev.openfeature.sdk.e2e.MockHook; import dev.openfeature.sdk.e2e.State; @@ -8,14 +12,9 @@ import io.cucumber.java.en.And; import io.cucumber.java.en.Given; import io.cucumber.java.en.Then; - import java.util.List; import java.util.Map; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - public class HookSteps { private final State state; @@ -53,7 +52,8 @@ public void assertHookCalled(String hookName) { public void theHooksShouldBeCalledWithEvaluationDetails(String hookNames, DataTable data) { for (String hookName : hookNames.split(", ")) { assertHookCalled(hookName); - FlagEvaluationDetails evaluationDetails = state.hook.getEvaluationDetails().get(hookName); + FlagEvaluationDetails evaluationDetails = + state.hook.getEvaluationDetails().get(hookName); assertNotNull(evaluationDetails); List> dataEntries = data.asMaps(); for (Map line : dataEntries) { From 3eb233e31f3deb6632478fd6f6d2ae80e4de6c96 Mon Sep 17 00:00:00 2001 From: "christian.lutnik" Date: Tue, 11 Feb 2025 08:50:13 +0100 Subject: [PATCH 3/5] fixup! feat: implement gherkin tests Signed-off-by: christian.lutnik --- .../dev/openfeature/sdk/FlagMetadataTest.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index f8b9ba58e..ccfbe2cc4 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -1,6 +1,8 @@ package dev.openfeature.sdk; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -9,7 +11,7 @@ class FlagMetadataTest { @Test @DisplayName("Test metadata payload construction and retrieval") - public void builder_validation() { + void builder_validation() { // given ImmutableMetadata flagMetadata = ImmutableMetadata.builder() .addString("string", "string") @@ -42,7 +44,7 @@ public void builder_validation() { @Test @DisplayName("Value type mismatch returns a null") - public void value_type_validation() { + void value_type_validation() { // given ImmutableMetadata flagMetadata = ImmutableMetadata.builder().addString("string", "string").build(); @@ -53,11 +55,31 @@ public void value_type_validation() { @Test @DisplayName("A null is returned if key does not exist") - public void notfound_error_validation() { + void notfound_error_validation() { // given ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); // then assertThat(flagMetadata.getBoolean("string")).isNull(); } + + @Test + @DisplayName("isEmpty returns true iff the metadata is empty") + void isEmpty_returns_true_if_metadata_is_empty() { + // given + ImmutableMetadata flagMetadata = ImmutableMetadata.builder().build(); + + // then + assertTrue(flagMetadata.isEmpty()); + } + + @Test + @DisplayName("isEmpty returns false iff the metadata is not empty") + void isEmpty_returns_false_if_metadata_is_not_empty() { + // given + ImmutableMetadata flagMetadata = ImmutableMetadata.builder().addString("a","b").build(); + + // then + assertFalse(flagMetadata.isEmpty()); + } } From 4aeac21b84f329a434102f08c6371cc53a3ce610 Mon Sep 17 00:00:00 2001 From: "christian.lutnik" Date: Tue, 11 Feb 2025 08:50:42 +0100 Subject: [PATCH 4/5] fixup! feat: implement gherkin tests Signed-off-by: christian.lutnik --- src/test/java/dev/openfeature/sdk/FlagMetadataTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java index ccfbe2cc4..26d0421cd 100644 --- a/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java +++ b/src/test/java/dev/openfeature/sdk/FlagMetadataTest.java @@ -77,7 +77,8 @@ void isEmpty_returns_true_if_metadata_is_empty() { @DisplayName("isEmpty returns false iff the metadata is not empty") void isEmpty_returns_false_if_metadata_is_not_empty() { // given - ImmutableMetadata flagMetadata = ImmutableMetadata.builder().addString("a","b").build(); + ImmutableMetadata flagMetadata = + ImmutableMetadata.builder().addString("a", "b").build(); // then assertFalse(flagMetadata.isEmpty()); From 2a4d3860c9748907572818086113d651253d46b5 Mon Sep 17 00:00:00 2001 From: Simon Schrottner Date: Wed, 19 Feb 2025 16:16:35 +0100 Subject: [PATCH 5/5] fixup: add version for dependency Signed-off-by: Simon Schrottner --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 1ab0abe05..d850e4f0c 100644 --- a/pom.xml +++ b/pom.xml @@ -146,6 +146,7 @@ io.cucumber cucumber-picocontainer + ${io.cucumber.version} test