diff --git a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java index 07cb9d2..6f7ab2e 100644 --- a/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java +++ b/src/main/java/com/devcycle/sdk/server/openfeature/DevCycleProvider.java @@ -16,6 +16,7 @@ import dev.openfeature.sdk.FeatureProvider; import dev.openfeature.sdk.ImmutableMetadata; import dev.openfeature.sdk.ImmutableMetadata.ImmutableMetadataBuilder; +import dev.openfeature.sdk.ImmutableTrackingEventDetails; import dev.openfeature.sdk.Metadata; import dev.openfeature.sdk.ProviderEvaluation; import dev.openfeature.sdk.Reason; @@ -214,6 +215,11 @@ public void track(String eventName, EvaluationContext context, TrackingEventDeta throw new ProviderNotReadyError("DevCycle client not initialized"); } + // OpenFeature passes null details when Client.track() is called without them + if (details == null) { + details = new ImmutableTrackingEventDetails(); + } + DevCycleUser user = DevCycleUser.fromEvaluationContext(context); try { BigDecimal eventValue = extractEventValue(details); diff --git a/src/test/java/com/devcycle/sdk/server/openfeature/DevCycleProviderTest.java b/src/test/java/com/devcycle/sdk/server/openfeature/DevCycleProviderTest.java index 51de0a3..3687f78 100644 --- a/src/test/java/com/devcycle/sdk/server/openfeature/DevCycleProviderTest.java +++ b/src/test/java/com/devcycle/sdk/server/openfeature/DevCycleProviderTest.java @@ -2,6 +2,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; @@ -13,14 +14,17 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.junit.MockitoJUnitRunner; import com.devcycle.sdk.server.common.api.IDevCycleClient; +import com.devcycle.sdk.server.common.model.DevCycleEvent; import com.devcycle.sdk.server.common.model.EvalReason; import com.devcycle.sdk.server.common.model.Variable; import dev.openfeature.sdk.ErrorCode; import dev.openfeature.sdk.ImmutableContext; +import dev.openfeature.sdk.OpenFeatureAPI; import dev.openfeature.sdk.ProviderEvaluation; import dev.openfeature.sdk.Reason; import dev.openfeature.sdk.Structure; @@ -32,6 +36,22 @@ @RunWith(MockitoJUnitRunner.class) public class DevCycleProviderTest { + @Test + public void testTrackWithoutDetails() throws Exception { + IDevCycleClient dvcClient = mock(IDevCycleClient.class); + when(dvcClient.isInitialized()).thenReturn(true); + + String domain = "track-without-details"; + OpenFeatureAPI.getInstance().setProviderAndWait(domain, new DevCycleProvider(dvcClient)); + OpenFeatureAPI.getInstance().getClient(domain).track("checkout-completed", new ImmutableContext("user-1234")); + + ArgumentCaptor event = ArgumentCaptor.forClass(DevCycleEvent.class); + verify(dvcClient).track(any(), event.capture()); + Assert.assertEquals("checkout-completed", event.getValue().getType()); + Assert.assertNull(event.getValue().getValue()); + Assert.assertEquals(new HashMap<>(), event.getValue().getMetaData()); + } + @Test public void testResolveClientNotInitialized() { IDevCycleClient dvcClient = mock(IDevCycleClient.class);