Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: consistent method chainability #913

Merged
merged 5 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/dev/openfeature/sdk/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ public interface Client extends Features, EventBus<Client> {
* Set the client-level evaluation context.
* @param ctx Client level context.
*/
void setEvaluationContext(EvaluationContext ctx);
Client setEvaluationContext(EvaluationContext ctx);

/**
* Adds hooks for evaluation.
* Hooks are run in the order they're added in the before stage. They are run in reverse order for all other stages.
*
* @param hooks The hook to add.
*/
void addHooks(Hook... hooks);
Client addHooks(Hook... hooks);

/**
* Fetch the hooks associated to this client.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/dev/openfeature/sdk/MutableContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ public MutableContext add(String key, List<Value> value) {
/**
* Override or set targeting key for this mutable context. Value should be non-null and non-empty to be accepted.
*/
public void setTargetingKey(String targetingKey) {
public MutableContext setTargetingKey(String targetingKey) {
if (targetingKey != null && !targetingKey.trim().isEmpty()) {
this.add(TARGETING_KEY, targetingKey);
}
return this;
}


Expand Down
3 changes: 2 additions & 1 deletion src/main/java/dev/openfeature/sdk/OpenFeatureAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ public Client getClient(@Nullable String name, @Nullable String version) {
/**
* {@inheritDoc}
*/
public void setEvaluationContext(EvaluationContext evaluationContext) {
public OpenFeatureAPI setEvaluationContext(EvaluationContext evaluationContext) {
try (AutoCloseableLock __ = lock.writeLockAutoCloseable()) {
this.evaluationContext = evaluationContext;
}
return this;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/dev/openfeature/sdk/OpenFeatureClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ public OpenFeatureClient(OpenFeatureAPI openFeatureAPI, String name, String vers
* {@inheritDoc}
*/
@Override
public void addHooks(Hook... hooks) {
public OpenFeatureClient addHooks(Hook... hooks) {
try (AutoCloseableLock __ = this.hooksLock.writeLockAutoCloseable()) {
this.clientHooks.addAll(Arrays.asList(hooks));
}
return this;
}

/**
Expand All @@ -76,10 +77,11 @@ public List<Hook> getHooks() {
* {@inheritDoc}
*/
@Override
public void setEvaluationContext(EvaluationContext evaluationContext) {
public OpenFeatureClient setEvaluationContext(EvaluationContext evaluationContext) {
try (AutoCloseableLock __ = contextLock.writeLockAutoCloseable()) {
this.evaluationContext = evaluationContext;
}
return this;
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/dev/openfeature/sdk/MutableContextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,19 @@ void mergeShouldRetainItsSubkeysWhenOverridingContextHasNoTargetingKey() {
Structure value = key1.asStructure();
assertArrayEquals(new Object[]{"key1_1"}, value.keySet().toArray());
}

@DisplayName("Ensure mutations are chainable")
@Test
void shouldAllowChainingOfMutations() {
MutableContext context = new MutableContext();
context.add("key1", "val1")
.add("key2", 2)
.setTargetingKey("TARGETING_KEY")
.add("key3", 3.0);

assertEquals("TARGETING_KEY", context.getTargetingKey());
assertEquals("val1", context.getValue("key1").asString());
assertEquals(2, context.getValue("key2").asInteger());
assertEquals(3.0, context.getValue("key3").asDouble());
}
}
9 changes: 9 additions & 0 deletions src/test/java/dev/openfeature/sdk/OpenFeatureAPITest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Collections;
import java.util.HashMap;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -78,4 +79,12 @@ void settingNamedClientProviderToNullErrors() {
void settingTransactionalContextPropagatorToNullErrors() {
assertThatCode(() -> api.setTransactionContextPropagator(null)).isInstanceOf(IllegalArgumentException.class);
}

@Test
void setEvaluationContextShouldAllowChaining() {
OpenFeatureClient client = new OpenFeatureClient(api, "name", "version");
EvaluationContext ctx = new ImmutableContext("targeting key", new HashMap<>());
OpenFeatureClient result = client.setEvaluationContext(ctx);
assertEquals(client, result);
}
}
30 changes: 30 additions & 0 deletions src/test/java/dev/openfeature/sdk/OpenFeatureClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
import java.util.*;

import dev.openfeature.sdk.fixtures.HookFixtures;

import org.junit.jupiter.api.*;
import org.mockito.Mockito;
import org.simplify4u.slf4jmock.LoggerMock;
import org.slf4j.Logger;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

class OpenFeatureClientTest implements HookFixtures {
Expand Down Expand Up @@ -67,4 +73,28 @@ void mergeContextTest() {

assertThat(result.getValue()).isTrue();
}

@Test
@DisplayName("addHooks should allow chaining by returning the same client instance")
void addHooksShouldAllowChaining() {
OpenFeatureAPI api = mock(OpenFeatureAPI.class);
OpenFeatureClient client = new OpenFeatureClient(api, "name", "version");
Hook<?> hook1 = Mockito.mock(Hook.class);
Hook<?> hook2 = Mockito.mock(Hook.class);

OpenFeatureClient result = client.addHooks(hook1, hook2);
assertEquals(client, result);
}

@Test
@DisplayName("setEvaluationContext should allow chaining by returning the same client instance")
void setEvaluationContextShouldAllowChaining() {
OpenFeatureAPI api = mock(OpenFeatureAPI.class);
OpenFeatureClient client = new OpenFeatureClient(api, "name", "version");
EvaluationContext ctx = new ImmutableContext("targeting key", new HashMap<>());

OpenFeatureClient result = client.setEvaluationContext(ctx);
assertEquals(client, result);
}

}
Loading