diff --git a/packages/core/src/flags/__tests__/FlagsClient.test.ts b/packages/core/src/flags/__tests__/FlagsClient.test.ts index 06903099c..4504f3cd1 100644 --- a/packages/core/src/flags/__tests__/FlagsClient.test.ts +++ b/packages/core/src/flags/__tests__/FlagsClient.test.ts @@ -58,6 +58,17 @@ jest.spyOn(NativeModules.DdFlags, 'setEvaluationContext').mockResolvedValue({ variationType: '', variationValue: '', extraLogging: {} + }, + 'test-flag-with-alloc-key': { + key: 'test-flag-with-alloc-key', + value: true, + allocationKey: 'alloc-abc', + variationKey: 'true', + reason: 'TARGETED', + doLog: true, + variationType: '', + variationValue: '', + extraLogging: {} } }); @@ -206,6 +217,21 @@ describe('FlagsClient', () => { }); }); + it('should populate allocationKey in details', async () => { + const flagsClient = DdFlags.getClient(); + await flagsClient.setEvaluationContext({ + targetingKey: 'test-user-1', + attributes: { country: 'US' } + }); + + const details = flagsClient.getBooleanDetails( + 'test-flag-with-alloc-key', + false + ); + + expect(details.allocationKey).toBe('alloc-abc'); + }); + it('should return TYPE_MISMATCH when using wrong typed accessor method', async () => { // Flag values are mocked in the __mocks__/react-native.ts file. const flagsClient = DdFlags.getClient(); diff --git a/packages/react-native-openfeature/__mocks__/react-native.ts b/packages/react-native-openfeature/__mocks__/react-native.ts new file mode 100644 index 000000000..855d5a39c --- /dev/null +++ b/packages/react-native-openfeature/__mocks__/react-native.ts @@ -0,0 +1,16 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const actualRN = require('react-native'); + +actualRN.NativeModules.DdFlags = { + enable: jest.fn(() => Promise.resolve()), + setEvaluationContext: jest.fn(() => Promise.resolve({})), + trackEvaluation: jest.fn(() => Promise.resolve()) +}; + +module.exports = actualRN; diff --git a/packages/react-native-openfeature/src/__tests__/provider.test.ts b/packages/react-native-openfeature/src/__tests__/provider.test.ts new file mode 100644 index 000000000..f20ac73e2 --- /dev/null +++ b/packages/react-native-openfeature/src/__tests__/provider.test.ts @@ -0,0 +1,79 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +import { DdFlags } from '@datadog/mobile-react-native'; +import { NativeModules } from 'react-native'; + +import { DatadogOpenFeatureProvider } from '../provider'; + +jest.spyOn(NativeModules.DdFlags, 'setEvaluationContext').mockResolvedValue({ + 'bool-flag': { + key: 'bool-flag', + value: true, + allocationKey: 'alloc-xyz', + variationKey: 'true', + reason: 'TARGETED', + doLog: true, + variationType: '', + variationValue: '', + extraLogging: {} + }, + 'flag-no-alloc': { + key: 'flag-no-alloc', + value: 'hello', + allocationKey: '', + variationKey: 'hello', + reason: 'STATIC', + doLog: true, + variationType: '', + variationValue: '', + extraLogging: {} + } +}); + +describe('DatadogOpenFeatureProvider', () => { + let provider: DatadogOpenFeatureProvider; + + beforeEach(async () => { + jest.clearAllMocks(); + + Object.assign(DdFlags, { + isFeatureEnabled: false, + clients: {} + }); + + await DdFlags.enable(); + + provider = new DatadogOpenFeatureProvider(); + await provider.initialize({ targetingKey: 'user-1' }); + }); + + describe('toFlagResolution / flagMetadata', () => { + it('should include allocationKey in flagMetadata when present', () => { + const result = provider.resolveBooleanEvaluation( + 'bool-flag', + false, + {}, + {} as any + ); + + expect(result.flagMetadata).toEqual({ + allocationKey: 'alloc-xyz' + }); + }); + + it('should return undefined flagMetadata when allocationKey is absent', () => { + const result = provider.resolveStringEvaluation( + 'flag-no-alloc', + 'default', + {}, + {} as any + ); + + expect(result.flagMetadata).toBeUndefined(); + }); + }); +}); diff --git a/packages/react-native-openfeature/src/provider.ts b/packages/react-native-openfeature/src/provider.ts index 6cbae29ca..4c4be7b6c 100644 --- a/packages/react-native-openfeature/src/provider.ts +++ b/packages/react-native-openfeature/src/provider.ts @@ -8,7 +8,8 @@ import { DdFlags } from '@datadog/mobile-react-native'; import type { FlagDetails, FlagsClient, - EvaluationContext as DdEvaluationContext + EvaluationContext as DdEvaluationContext, + PrimitiveValue } from '@datadog/mobile-react-native'; import { OpenFeatureEventEmitter, ErrorCode } from '@openfeature/web-sdk'; import type { @@ -19,7 +20,6 @@ import type { Provider, ProviderMetadata, ResolutionDetails, - PrimitiveValue, ProviderEventEmitter, ProviderEvents } from '@openfeature/web-sdk';