From 7640e3b72401a66ffe071e35b7ab5c7b8ba64bc3 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 22 Oct 2026 15:49:59 +0000 Subject: [PATCH] test: refresh shared FFE fixtures and assert result metadata Consume the latest candidate fixture revision and check serial IDs and logging decisions in core and Node, preserving repeated evaluations on the same configuration/provider. Environment: Datadog workspace --- packages/core/test/TestCaseResult.types.ts | 2 ++ .../core/test/evaluation/flags-v1.spec.ts | 16 ++++++++++-- packages/core/test/ffe-system-test-data | 2 +- packages/node-server/test/ffe-system.spec.ts | 25 +++++++++++++++---- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/core/test/TestCaseResult.types.ts b/packages/core/test/TestCaseResult.types.ts index 60420819..d7d6daf3 100644 --- a/packages/core/test/TestCaseResult.types.ts +++ b/packages/core/test/TestCaseResult.types.ts @@ -13,6 +13,8 @@ export interface TestCase { value: FlagValue reason: string errorCode?: string + serialId?: number | null + doLog?: boolean variant?: string flagMetadata?: PrecomputedFlagMetadata } diff --git a/packages/core/test/evaluation/flags-v1.spec.ts b/packages/core/test/evaluation/flags-v1.spec.ts index 67875377..b5bcd6ca 100644 --- a/packages/core/test/evaluation/flags-v1.spec.ts +++ b/packages/core/test/evaluation/flags-v1.spec.ts @@ -26,6 +26,17 @@ describe('Universal Flag Configuration V1', () => { const ufcJson = fs.readFileSync(path.join(fixtureDirectory, 'ufc-config.json'), 'utf8') return JSON.parse(ufcJson) as UniversalFlagConfigurationV1 } + // Keep ordered repeated cases on the same prepared configuration. + const configuration = getUFC() + + const expectMetadata = (details: ResolutionDetails, expected: TestCase['result']) => { + if (expected.serialId !== undefined) { + expect(details.flagMetadata?.__dd_split_serial_id ?? null).toBe(expected.serialId) + } + if (expected.doLog !== undefined) { + expect(details.flagMetadata?.__dd_do_log).toBe(expected.doLog) + } + } const getTestCaseFileNames = (): string[] => { const fixtureFiles = fs.readdirSync(path.join(fixtureDirectory, 'evaluation-cases')).sort() @@ -45,7 +56,6 @@ describe('Universal Flag Configuration V1', () => { context: EvaluationContext, immediate: ExperimentationOptOutOption = false ): ResolutionDetails => { - const configuration = getUFC() if (testCase.variationType === 'BOOLEAN') { return evaluateRulesBasedConfiguration( configuration, @@ -94,7 +104,7 @@ describe('Universal Flag Configuration V1', () => { } it.each(['constructor', '__proto__'])('treats inherited JSON flag key %s as missing', (flagKey) => { - expect(evaluateRulesBasedConfiguration(getUFC(), 'boolean', flagKey, false, {}, logger)).toMatchObject({ + expect(evaluateRulesBasedConfiguration(configuration, 'boolean', flagKey, false, {}, logger)).toMatchObject({ value: false, reason: 'ERROR', errorCode: 'FLAG_NOT_FOUND', @@ -119,6 +129,7 @@ describe('Universal Flag Configuration V1', () => { if (testCase.result.errorCode !== undefined || testCase.result.reason !== 'ERROR') { expect(details.errorCode).toEqual(testCase.result.errorCode) } + expectMetadata(details, testCase.result) }) for (const [capability, mode] of [ @@ -134,6 +145,7 @@ describe('Universal Flag Configuration V1', () => { expect(details.value).toStrictEqual(expected.value) expect(details.reason).toEqual(expected.reason) expect(details.errorCode).toEqual(expected.errorCode) + expectMetadata(details, expected) }) } } diff --git a/packages/core/test/ffe-system-test-data b/packages/core/test/ffe-system-test-data index 1c831fed..b2887620 160000 --- a/packages/core/test/ffe-system-test-data +++ b/packages/core/test/ffe-system-test-data @@ -1 +1 @@ -Subproject commit 1c831fed02a428a1b0a4ac412da9b773e22df257 +Subproject commit b28876200152f00c7d5eb04616f721afa5955c1d diff --git a/packages/node-server/test/ffe-system.spec.ts b/packages/node-server/test/ffe-system.spec.ts index 81d3657a..054b7c62 100644 --- a/packages/node-server/test/ffe-system.spec.ts +++ b/packages/node-server/test/ffe-system.spec.ts @@ -15,6 +15,8 @@ type SystemTestCase = { result: { value: FlagValue reason: string + serialId?: number | null + doLog?: boolean } } @@ -52,10 +54,10 @@ function getTestCases(testCaseFileName: string): SystemTestCase[] { ) as SystemTestCase[] } -async function evaluateTestCase(testCase: SystemTestCase): Promise> { - const provider = new DatadogNodeServerProvider({ exposureChannel }) - provider.setConfiguration(configuration) - +async function evaluateTestCase( + provider: DatadogNodeServerProvider, + testCase: SystemTestCase +): Promise> { const context = { ...(testCase.targetingKey === null ? {} : { targetingKey: testCase.targetingKey }), ...testCase.attributes, @@ -77,12 +79,25 @@ async function evaluateTestCase(testCase: SystemTestCase): Promise { describe.each(getTestCaseFileNames())('should evaluate for %s', (testCaseFileName) => { const testCases = getTestCases(testCaseFileName) + let provider: DatadogNodeServerProvider + + beforeAll(() => { + // Repeated cases must exercise the same provider in fixture order. + provider = new DatadogNodeServerProvider({ exposureChannel }) + provider.setConfiguration(configuration) + }) it.each(testCases)('with context $targetingKey and flag $flag', async (testCase) => { - const details = await evaluateTestCase(testCase) + const details = await evaluateTestCase(provider, testCase) expect(details.value).toEqual(testCase.result.value) expect(details.reason).toEqual(testCase.result.reason) + if (testCase.result.serialId !== undefined) { + expect(details.flagMetadata?.__dd_split_serial_id ?? null).toBe(testCase.result.serialId) + } + if (testCase.result.doLog !== undefined) { + expect(details.flagMetadata?.__dd_do_log).toBe(testCase.result.doLog) + } }) }) })