diff --git a/specification b/specification index 57495a9..cdffe1e 160000 --- a/specification +++ b/specification @@ -1 +1 @@ -Subproject commit 57495a9dc1155e4c079aba1b91663a4ee501dca7 +Subproject commit cdffe1e884518bde7e43065a252ecdcbd4fb209e diff --git a/src/main/java/com/octopus/openfeature/provider/FeatureToggleEvaluation.java b/src/main/java/com/octopus/openfeature/provider/FeatureToggleEvaluation.java index c394baa..3d2db59 100644 --- a/src/main/java/com/octopus/openfeature/provider/FeatureToggleEvaluation.java +++ b/src/main/java/com/octopus/openfeature/provider/FeatureToggleEvaluation.java @@ -3,35 +3,30 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Collections; -import java.util.ArrayList; import java.util.List; +import java.util.Optional; class FeatureToggleEvaluation { - private final String name; private final String slug; private final boolean isEnabled; + private final String evaluationKey; private final List segments; + private final Integer clientRolloutPercentage; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) FeatureToggleEvaluation( - @JsonProperty("name") String name, - @JsonProperty("slug") String slug, - @JsonProperty("isEnabled") boolean isEnabled, - @JsonProperty("segments") List segments + @JsonProperty(value = "slug", required = true) String slug, + @JsonProperty(value = "isEnabled", required = true) boolean isEnabled, + @JsonProperty("evaluationKey") String evaluationKey, + @JsonProperty("segments") List segments, + @JsonProperty("clientRolloutPercentage") Integer clientRolloutPercentage ) { - this.name = name; this.slug = slug; this.isEnabled = isEnabled; - this.segments = new ArrayList<>(); - if (segments != null) { - this.segments.addAll(segments); - } - } - - public String getName() { - return name; + this.evaluationKey = evaluationKey; + this.segments = segments == null ? null : List.copyOf(segments); + this.clientRolloutPercentage = clientRolloutPercentage; } public String getSlug() { @@ -42,7 +37,19 @@ public boolean isEnabled() { return isEnabled; } - public List getSegments() { - return Collections.unmodifiableList(segments); + public Optional getEvaluationKey() { + return Optional.ofNullable(evaluationKey); + } + + public Optional> getSegments() { + return Optional.ofNullable(segments); + } + + public boolean hasSegments() { + return segments != null && !segments.isEmpty(); + } + + public Optional getClientRolloutPercentage() { + return Optional.ofNullable(clientRolloutPercentage); } } diff --git a/src/main/java/com/octopus/openfeature/provider/OctopusClient.java b/src/main/java/com/octopus/openfeature/provider/OctopusClient.java index f22e455..b31bd60 100644 --- a/src/main/java/com/octopus/openfeature/provider/OctopusClient.java +++ b/src/main/java/com/octopus/openfeature/provider/OctopusClient.java @@ -1,7 +1,6 @@ package com.octopus.openfeature.provider; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; @@ -65,7 +64,7 @@ FeatureToggles getFeatureToggleEvaluationManifest() logger.log(System.Logger.Level.WARNING,String.format("Feature toggle response from %s did not contain expected ContentHash header", manifestURI.toString())); return null; } - List evaluations = OctopusObjectMapper.INSTANCE.readValue(httpResponse.body(), new TypeReference>(){}); + List evaluations = OctopusObjectMapper.INSTANCE.readValue(httpResponse.body(), new TypeReference<>(){}); return new FeatureToggles(evaluations, Base64.getDecoder().decode(contentHashHeader.get())); } catch (Exception e) { logger.log(System.Logger.Level.WARNING, "Unable to query Octopus Feature Toggle service", e); @@ -83,16 +82,12 @@ private URI getCheckURI() { private URI getManifestURI() { try { - return new URL(config.getServerUri().toURL(), "/api/featuretoggles/v3/").toURI(); + return new URL(config.getServerUri().toURL(), "/api/toggles/evaluations/v3/").toURI(); } catch (MalformedURLException | URISyntaxException ignored) // we know this URL is well-formed { } return null; } - private Boolean isSuccessStatusCode(int statusCode) { - return statusCode >= 200 && statusCode < 300; - } - // This class needs to be static to allow deserialization private static class FeatureToggleCheckResponse { public byte[] contentHash; diff --git a/src/main/java/com/octopus/openfeature/provider/OctopusContext.java b/src/main/java/com/octopus/openfeature/provider/OctopusContext.java index 7ce50d5..6b85b03 100644 --- a/src/main/java/com/octopus/openfeature/provider/OctopusContext.java +++ b/src/main/java/com/octopus/openfeature/provider/OctopusContext.java @@ -2,9 +2,9 @@ import dev.openfeature.sdk.*; import dev.openfeature.sdk.exceptions.FlagNotFoundError; +import dev.openfeature.sdk.exceptions.ParseError; import java.util.List; -import java.util.Map; import static java.util.stream.Collectors.groupingBy; @@ -20,8 +20,10 @@ class OctopusContext { static OctopusContext empty() { return new OctopusContext(new FeatureToggles(List.of(), new byte[0])); } - - byte[] getContentHash() { return featureToggles.getContentHash(); } + + byte[] getContentHash() { + return featureToggles.getContentHash(); + } ProviderEvaluation evaluate(String slug, Boolean defaultValue, EvaluationContext evaluationContext) { // find the feature toggle matching the slug @@ -29,26 +31,40 @@ ProviderEvaluation evaluate(String slug, Boolean defaultValue, Evaluati // this exception will be handled by OpenFeature, and the default value will be used if (toggleValue == null) { - throw new FlagNotFoundError(); + throw new FlagNotFoundError(); + } + + if (missingRequiredPropertiesForClientSideEvaluation(toggleValue)) { + throw new ParseError("Feature toggle " + toggleValue.getSlug() + " is missing necessary information for client-side evaluation."); } - - // if the toggle is disabled, or if it has no segments, then we don't need to evaluate dynamically - if (!toggleValue.isEnabled() || toggleValue.getSegments().isEmpty()) { + + // if the toggle is disabled, or if it has no segments, then we don't need to evaluate dynamically + if (!toggleValue.isEnabled() || !toggleValue.hasSegments()) { return ProviderEvaluation.builder() .value(toggleValue.isEnabled()) .reason(Reason.DEFAULT.toString()) .build(); } - - // If the toggle is enabled and has segments configured, then we need to evaluate dynamically, + + // If the toggle is enabled and has segments configured, then we need to evaluate dynamically, // checking the context matches the segments return ProviderEvaluation.builder() - .value(MatchesSegment(evaluationContext, toggleValue.getSegments())) + .value(matchesSegment(evaluationContext, toggleValue.getSegments().orElseThrow())) // checked in hasSegments .reason(Reason.TARGETING_MATCH.toString()) .build(); } - private Boolean MatchesSegment(EvaluationContext evaluationContext, List segments) { + private boolean missingRequiredPropertiesForClientSideEvaluation(FeatureToggleEvaluation evaluation) { + if (!evaluation.isEnabled()) { + return false; + } + + return evaluation.getClientRolloutPercentage().isEmpty() + || evaluation.getEvaluationKey().isEmpty() + || evaluation.getSegments().isEmpty(); + } + + private Boolean matchesSegment(EvaluationContext evaluationContext, List segments) { if (evaluationContext == null) { return false; } diff --git a/src/test/java/com/octopus/openfeature/provider/FeatureToggleEvaluationDeserializationTests.java b/src/test/java/com/octopus/openfeature/provider/FeatureToggleEvaluationDeserializationTests.java index 4607b62..597b76a 100644 --- a/src/test/java/com/octopus/openfeature/provider/FeatureToggleEvaluationDeserializationTests.java +++ b/src/test/java/com/octopus/openfeature/provider/FeatureToggleEvaluationDeserializationTests.java @@ -7,7 +7,7 @@ import java.io.InputStream; import java.util.List; -import java.util.Map; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -28,10 +28,12 @@ private void assertSegmentsContain(List segments, Segment... expected) void shouldDeserializeEnabledToggle() throws Exception { FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-enabled-no-segments.json"), FeatureToggleEvaluation.class); - assertThat(result.getName()).isEqualTo("My Feature"); assertThat(result.getSlug()).isEqualTo("my-feature"); assertThat(result.isEnabled()).isTrue(); - assertThat(result.getSegments()).isEmpty(); + assertThat(result.getEvaluationKey()).hasValue("eval-key-1"); + assertThat(result.getSegments()).isPresent(); + assertThat(result.getSegments().orElseThrow()).isEmpty(); + assertThat(result.getClientRolloutPercentage()).hasValue(100); } @Test @@ -39,13 +41,16 @@ void shouldDeserializeDisabledToggle() throws Exception { FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-disabled.json"), FeatureToggleEvaluation.class); assertThat(result.isEnabled()).isFalse(); + assertThat(result.getEvaluationKey()).isEmpty(); + assertThat(result.getSegments()).isEmpty(); + assertThat(result.getClientRolloutPercentage()).isEmpty(); } @Test void shouldDeserializeToggleWithMissingSegmentsField() throws Exception { FeatureToggleEvaluation result = objectMapper.readValue(resource("toggle-missing-segments.json"), FeatureToggleEvaluation.class); - assertThat(result.getSegments()).isNotNull().isEmpty(); + assertThat(result.getSegments()).isEmpty(); } @Test @@ -53,8 +58,11 @@ void shouldDeserializeToggleWithSegments() throws Exception { FeatureToggleEvaluation result = objectMapper.readValue( resource("toggle-with-segments.json"), FeatureToggleEvaluation.class); - assertThat(result.getSegments()).hasSize(2); - assertSegmentsContain(result.getSegments(), + var segments = result.getSegments().orElseThrow(); + + assertThat(segments).hasSize(2); + assertSegmentsContain( + segments, new Segment("license-type", "free"), new Segment("country", "au") ); @@ -86,13 +94,13 @@ void shouldDeserializeListOfTogglesWithVariousFieldCasings() throws Exception { assertThat(result).hasSize(3); assertThat(result.get(0).getSlug()).isEqualTo("feature-a"); assertThat(result.get(0).isEnabled()).isTrue(); - assertSegmentsContain(result.get(0).getSegments(), new Segment("license-type", "free")); + assertSegmentsContain(result.get(0).getSegments().orElseThrow(), new Segment("license-type", "free")); assertThat(result.get(1).getSlug()).isEqualTo("feature-b"); assertThat(result.get(1).isEnabled()).isTrue(); - assertSegmentsContain(result.get(1).getSegments(), new Segment("plan", "enterprise")); + assertSegmentsContain(result.get(1).getSegments().orElseThrow(), new Segment("plan", "enterprise")); assertThat(result.get(2).getSlug()).isEqualTo("feature-c"); assertThat(result.get(2).isEnabled()).isTrue(); - assertSegmentsContain(result.get(2).getSegments(), new Segment("country", "au")); + assertSegmentsContain(result.get(2).getSegments().orElseThrow(), new Segment("country", "au")); } @Test @@ -121,9 +129,8 @@ void shouldIgnoreExtraneousProperties() throws Exception { FeatureToggleEvaluation result = objectMapper.readValue( resource("toggle-with-extraneous-properties.json"), FeatureToggleEvaluation.class); - assertThat(result.getName()).isEqualTo("My Feature"); assertThat(result.getSlug()).isEqualTo("my-feature"); assertThat(result.isEnabled()).isTrue(); - assertSegmentsContain(result.getSegments(), new Segment("license-type", "free")); + assertSegmentsContain(result.getSegments().orElseThrow(), new Segment("license-type", "free")); } } diff --git a/src/test/java/com/octopus/openfeature/provider/OctopusContextTests.java b/src/test/java/com/octopus/openfeature/provider/OctopusContextTests.java index 5cdea37..58810c7 100644 --- a/src/test/java/com/octopus/openfeature/provider/OctopusContextTests.java +++ b/src/test/java/com/octopus/openfeature/provider/OctopusContextTests.java @@ -4,23 +4,22 @@ import dev.openfeature.sdk.MutableContext; import dev.openfeature.sdk.Reason; import dev.openfeature.sdk.exceptions.FlagNotFoundError; +import dev.openfeature.sdk.exceptions.ParseError; import org.junit.jupiter.api.*; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; class OctopusContextTests { - + private static final FeatureToggles sampleFeatureToggles = new FeatureToggles( Arrays.asList( - new FeatureToggleEvaluation("Enabled Feature", "enabled-feature", true, null), - new FeatureToggleEvaluation("Disabled Feature", "disabled-feature", false, null), - new FeatureToggleEvaluation("Feature With Segments", "feature-with-segments", true, Arrays.asList(new Segment("license-type", "free"), new Segment("country", "au")) ) + new FeatureToggleEvaluation("enabled-feature", true, UUID.randomUUID().toString(), Collections.emptyList(), 100), + new FeatureToggleEvaluation("disabled-feature", false, null, null, null), + new FeatureToggleEvaluation("feature-with-segments", true, UUID.randomUUID().toString(), Arrays.asList(new Segment("license-type", "free"), new Segment("country", "au")), 100) ), new byte[0] ); @@ -29,11 +28,11 @@ class OctopusContextTests { @Test void shouldEvaluateToTrueIfFeatureToggleIsPresentAndEnabled() { var subject = new OctopusContext(sampleFeatureToggles); - var result = subject.evaluate("enabled-feature", false, null); - + var result = subject.evaluate("enabled-feature", false, null); + assertThat(result.getValue()).isTrue(); } - + @Test void keyShouldBeCaseInsensitiveWhenEvaluating() { var subject = new OctopusContext(sampleFeatureToggles); @@ -41,27 +40,71 @@ void keyShouldBeCaseInsensitiveWhenEvaluating() { assertThat(result.getValue()).isTrue(); } - + @Test void shouldEvaluateToFalseIfFeatureToggleIsPresentAndDisabled() { var subject = new OctopusContext(sampleFeatureToggles); - var result = subject.evaluate("disabled-feature", false, null); - + var result = subject.evaluate("disabled-feature", false, null); + assertThat(result.getValue()).isFalse(); } - + @Test void shouldThrowFlagNotFoundErrorIfFeatureToggleIsNotFound() { var defaultValue = false; var subject = new OctopusContext(sampleFeatureToggles); assertThrows(FlagNotFoundError.class, () -> subject.evaluate("key-not-present", defaultValue, null)); - } - + } + + @Test + void shouldThrowParseErrorWhenEnabledToggleIsMissingEvaluationKey() { + var toggles = new FeatureToggles( + List.of(new FeatureToggleEvaluation("feature-a", true, null, Collections.emptyList(), 100)), + new byte[0] + ); + var subject = new OctopusContext(toggles); + var ex = assertThrows(ParseError.class, () -> subject.evaluate("feature-a", false, null)); + assertThat(ex.getMessage()).contains("feature-a"); + } + + @Test + void shouldThrowParseErrorWhenEnabledToggleIsMissingSegments() { + var toggles = new FeatureToggles( + List.of(new FeatureToggleEvaluation("feature-b", true, "evaluation-key", null, 100)), + new byte[0] + ); + var subject = new OctopusContext(toggles); + var ex = assertThrows(ParseError.class, () -> subject.evaluate("feature-b", false, null)); + assertThat(ex.getMessage()).contains("feature-b"); + } + + @Test + void shouldThrowParseErrorWhenEnabledToggleIsMissingClientRolloutPercentage() { + var toggles = new FeatureToggles( + List.of(new FeatureToggleEvaluation("feature-c", true, "evaluation-key", Collections.emptyList(), null)), + new byte[0] + ); + var subject = new OctopusContext(toggles); + var ex = assertThrows(ParseError.class, () -> subject.evaluate("feature-c", false, null)); + assertThat(ex.getMessage()).contains("feature-c"); + } + + @Test + void shouldThrowParseErrorWhenEnabledToggleIsMissingAllClientEvaluationFields() { + var toggles = new FeatureToggles( + List.of(new FeatureToggleEvaluation("feature-d", true, null, null, null)), + new byte[0] + ); + var subject = new OctopusContext(toggles); + var ex = assertThrows(ParseError.class, () -> subject.evaluate("feature-d", true, null)); + assertThat(ex.getMessage()).contains("feature-d"); + } + @TestFactory Iterable shouldCorrectlyDynamicallyEvaluateSegmentsWhenSupplied() { return Arrays.asList( - - evaluationTest("no-segments", "enabled-feature", + + evaluationTest("no-segments", "enabled-feature", buildEvaluationContext(List.of( Map.entry("user-id", "123456") )), true, Reason.DEFAULT.toString()), @@ -70,7 +113,7 @@ Iterable shouldCorrectlyDynamicallyEvaluateSegmentsWhenSupplied() { buildEvaluationContext(List.of() ), false, Reason.TARGETING_MATCH.toString()), - evaluationTest("all-segments-match", "feature-with-segments", + evaluationTest("all-segments-match", "feature-with-segments", buildEvaluationContext(Arrays.asList( Map.entry("license-type", "free"), Map.entry("country", "au")) ), true, Reason.TARGETING_MATCH.toString()), @@ -91,23 +134,23 @@ Iterable shouldCorrectlyDynamicallyEvaluateSegmentsWhenSupplied() { ), false, Reason.TARGETING_MATCH.toString()) ); } - - private DynamicTest evaluationTest(String testName, String featureToggleKey, EvaluationContext evaluationContext, + + private DynamicTest evaluationTest(String testName, String featureToggleKey, EvaluationContext evaluationContext, boolean expectedResult, String expectedReason) { - return DynamicTest.dynamicTest(testName, () -> { - var subject = new OctopusContext(sampleFeatureToggles); - var result = subject.evaluate(featureToggleKey, false, evaluationContext); - assertThat(result.getValue()).isEqualTo(expectedResult); - assertThat(result.getReason()).isEqualTo(expectedReason); - }); + return DynamicTest.dynamicTest(testName, () -> { + var subject = new OctopusContext(sampleFeatureToggles); + var result = subject.evaluate(featureToggleKey, false, evaluationContext); + assertThat(result.getValue()).isEqualTo(expectedResult); + assertThat(result.getReason()).isEqualTo(expectedReason); + }); } - + private EvaluationContext buildEvaluationContext(List> entries) { var context = new MutableContext(); entries.forEach(entry -> { context.add(entry.getKey(), entry.getValue()); }); return context; - } - + } + } diff --git a/src/test/java/com/octopus/openfeature/provider/Server.java b/src/test/java/com/octopus/openfeature/provider/Server.java index 49f3c77..ea2d431 100644 --- a/src/test/java/com/octopus/openfeature/provider/Server.java +++ b/src/test/java/com/octopus/openfeature/provider/Server.java @@ -42,7 +42,7 @@ class Server { */ String configure(String responseJson) { String token = UUID.randomUUID().toString(); - wireMock.stubFor(get(urlPathEqualTo("/api/featuretoggles/v3/")) + wireMock.stubFor(get(urlPathEqualTo("/api/toggles/evaluations/v3/")) .withHeader("Authorization", equalTo("Bearer " + token)) .willReturn(aResponse() .withStatus(200) diff --git a/src/test/java/com/octopus/openfeature/provider/SpecificationTests.java b/src/test/java/com/octopus/openfeature/provider/SpecificationTests.java index e6fe337..8e51d96 100644 --- a/src/test/java/com/octopus/openfeature/provider/SpecificationTests.java +++ b/src/test/java/com/octopus/openfeature/provider/SpecificationTests.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -49,6 +50,7 @@ void shutdownApi() { @ParameterizedTest(name = "[{0}] {1}") @MethodSource("fixtureTestCases") + @Disabled("Requires either old endpoint to be used, or client rollout percentage to be implemented") void evaluate(String fileName, String description, String responseJson, FixtureCase testCase) { String token = server.configure(responseJson); OctopusConfiguration config = new OctopusConfiguration(token); diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-disabled.json b/src/test/resources/com/octopus/openfeature/provider/toggle-disabled.json index f09370d..fb45a0a 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-disabled.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-disabled.json @@ -1,6 +1,4 @@ { - "name": "My Feature", "slug": "my-feature", - "isEnabled": false, - "segments": null + "isEnabled": false } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-enabled-no-segments.json b/src/test/resources/com/octopus/openfeature/provider/toggle-enabled-no-segments.json index e9d17e9..7cd079d 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-enabled-no-segments.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-enabled-no-segments.json @@ -1,6 +1,7 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, - "segments": null + "evaluationKey": "eval-key-1", + "segments": [], + "clientRolloutPercentage": 100 } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-list.json b/src/test/resources/com/octopus/openfeature/provider/toggle-list.json index ea6d15f..a38a11d 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-list.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-list.json @@ -1,14 +1,13 @@ [ { - "name": "Feature A", "slug": "feature-a", "isEnabled": true, - "segments": null + "evaluationKey": "eval-key-a", + "segments": [], + "clientRolloutPercentage": 100 }, { - "name": "Feature B", "slug": "feature-b", - "isEnabled": false, - "segments": null + "isEnabled": false } ] diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-missing-segments.json b/src/test/resources/com/octopus/openfeature/provider/toggle-missing-segments.json index 285d13e..0d83bb9 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-missing-segments.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-missing-segments.json @@ -1,5 +1,6 @@ { - "name": "My Feature", "slug": "my-feature", - "isEnabled": true + "isEnabled": true, + "evaluationKey": "eval-key-1", + "clientRolloutPercentage": 100 } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key-and-value.json b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key-and-value.json index 11669cf..8a0b496 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key-and-value.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key-and-value.json @@ -1,8 +1,9 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, + "evaluationKey": "eval-key-1", "segments": [ {} - ] + ], + "clientRolloutPercentage": 100 } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key.json b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key.json index 7bf7e21..9ddffb0 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-key.json @@ -1,10 +1,11 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, + "evaluationKey": "eval-key-1", "segments": [ { "value": "free" } - ] + ], + "clientRolloutPercentage": 100 } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-value.json b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-value.json index b4f2137..836dd6b 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-value.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-segment-missing-value.json @@ -1,10 +1,11 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, + "evaluationKey": "eval-key-1", "segments": [ { "key": "license-type" } - ] + ], + "clientRolloutPercentage": 100 } diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-with-extraneous-properties.json b/src/test/resources/com/octopus/openfeature/provider/toggle-with-extraneous-properties.json index 39b78d1..87d4c9d 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-with-extraneous-properties.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-with-extraneous-properties.json @@ -1,7 +1,7 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, + "evaluationKey": "eval-key-1", "segments": [ { "key": "license-type", @@ -9,6 +9,7 @@ "more": "data" } ], + "clientRolloutPercentage": 100, "foo": "bar", "qux": 123, "wux": { diff --git a/src/test/resources/com/octopus/openfeature/provider/toggle-with-segments.json b/src/test/resources/com/octopus/openfeature/provider/toggle-with-segments.json index 88ae4f0..f73c58a 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggle-with-segments.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggle-with-segments.json @@ -1,7 +1,7 @@ { - "name": "My Feature", "slug": "my-feature", "isEnabled": true, + "evaluationKey": "eval-key-1", "segments": [ { "key": "license-type", @@ -11,5 +11,6 @@ "key": "country", "value": "au" } - ] + ], + "clientRolloutPercentage": 100 } \ No newline at end of file diff --git a/src/test/resources/com/octopus/openfeature/provider/toggles-with-different-field-capitalisation.json b/src/test/resources/com/octopus/openfeature/provider/toggles-with-different-field-capitalisation.json index 6f0e5d2..9f56d61 100644 --- a/src/test/resources/com/octopus/openfeature/provider/toggles-with-different-field-capitalisation.json +++ b/src/test/resources/com/octopus/openfeature/provider/toggles-with-different-field-capitalisation.json @@ -1,35 +1,38 @@ [ { - "NAME": "Feature A", "SLUG": "feature-a", "ISENABLED": true, + "EVALUATIONKEY": "eval-key-a", "SEGMENTS": [ { "KEY": "license-type", "VALUE": "free" } - ] + ], + "CLIENTROLLOUTPERCENTAGE": 100 }, { - "Name": "Feature B", "Slug": "feature-b", "IsEnabled": true, + "EvaluationKey": "eval-key-b", "Segments": [ { "Key": "plan", "Value": "enterprise" } - ] + ], + "ClientRolloutPercentage": 100 }, { - "nAmE": "Feature C", "sLuG": "feature-c", "iSeNaBlEd": true, + "eVaLuAtIoNkEy": "eval-key-c", "sEgMeNtS": [ { "kEy": "country", "vAlUe": "au" } - ] + ], + "cLiEnTrOlLoUtPeRcEnTaGe": 100 } ]