Skip to content

Commit 95a656d

Browse files
committed
Add client-side feature event and allFlags test.
1 parent eb42068 commit 95a656d

File tree

6 files changed

+135
-2
lines changed

6 files changed

+135
-2
lines changed

packages/shared/sdk-client/__tests__/LDClientImpl.events.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,45 @@ describe('sdk-client object', () => {
199199
expect.stringMatching(/was called with a non-numeric/),
200200
);
201201
});
202+
203+
it('sends events for prerequisite flags', async () => {
204+
await ldc.identify({ kind: 'user', key: 'bob' });
205+
ldc.variation('has-prereq-depth-1', false);
206+
ldc.flush();
207+
208+
// Prerequisite evaluation event should be emitted before the evaluation event for the flag
209+
// being evaluated.
210+
expect(mockedSendEvent).toHaveBeenNthCalledWith(
211+
2,
212+
expect.objectContaining({
213+
context: expect.anything(),
214+
creationDate: expect.any(Number),
215+
default: undefined,
216+
key: 'is-prereq',
217+
kind: 'feature',
218+
samplingRatio: 1,
219+
trackEvents: true,
220+
value: true,
221+
variation: 0,
222+
version: 1,
223+
withReasons: false,
224+
}),
225+
);
226+
expect(mockedSendEvent).toHaveBeenNthCalledWith(
227+
3,
228+
expect.objectContaining({
229+
context: expect.anything(),
230+
creationDate: expect.any(Number),
231+
default: false,
232+
key: 'has-prereq-depth-1',
233+
kind: 'feature',
234+
samplingRatio: 1,
235+
trackEvents: true,
236+
value: true,
237+
variation: 0,
238+
version: 4,
239+
withReasons: false,
240+
}),
241+
);
242+
});
202243
});

packages/shared/sdk-client/__tests__/evaluation/mockResponse.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,24 @@
5454
"value": true,
5555
"variation": 0,
5656
"trackEvents": false
57+
},
58+
"is-prereq": {
59+
"value": true,
60+
"variation": 0,
61+
"reason": {
62+
"kind": "FALLTHROUGH"
63+
},
64+
"version": 1,
65+
"trackEvents": true
66+
},
67+
"has-prereq-depth-1": {
68+
"value": true,
69+
"variation": 0,
70+
"prerequisites": ["is-prereq"],
71+
"reason": {
72+
"kind": "FALLTHROUGH"
73+
},
74+
"version": 4,
75+
"trackEvents": true
5776
}
5877
}

packages/shared/sdk-client/src/LDClientImpl.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ export default class LDClientImpl implements LDClient {
535535
return createErrorEvaluationDetail(ErrorKinds.FlagNotFound, defaultValue);
536536
}
537537

538-
const { reason, value, variation } = foundItem.flag;
538+
const { reason, value, variation, prerequisites } = foundItem.flag;
539539

540540
if (typeChecker) {
541541
const [matched, type] = typeChecker(value);
@@ -558,11 +558,27 @@ export default class LDClientImpl implements LDClient {
558558
}
559559
}
560560

561-
const successDetail = createSuccessEvaluationDetail(value, variation, reason);
561+
const successDetail = createSuccessEvaluationDetail(value, variation, reason, prerequisites);
562562
if (value === undefined || value === null) {
563563
this.logger.debug('Result value is null. Providing default value.');
564564
successDetail.value = defaultValue;
565565
}
566+
567+
successDetail.prerequisites?.forEach((prereqKey) => {
568+
const prereqFlag = this.flagManager.get(prereqKey);
569+
if (prereqFlag) {
570+
this.eventProcessor?.sendEvent(
571+
eventFactory.evalEventClient(
572+
prereqKey,
573+
prereqFlag.flag.value,
574+
undefined,
575+
prereqFlag.flag,
576+
evalContext,
577+
prereqFlag.flag.reason,
578+
),
579+
);
580+
}
581+
});
566582
this.eventProcessor?.sendEvent(
567583
eventFactory.evalEventClient(
568584
flagKey,

packages/shared/sdk-client/src/evaluation/evaluationDetail.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ export function createSuccessEvaluationDetail(
1717
value: LDFlagValue,
1818
variationIndex?: number,
1919
reason?: LDEvaluationReason,
20+
prerequisites?: string[],
2021
): LDEvaluationDetail {
2122
return {
2223
value,
2324
variationIndex: variationIndex ?? null,
2425
reason: reason ?? null,
26+
prerequisites,
2527
};
2628
}

packages/shared/sdk-client/src/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface Flag {
1010
reason?: LDEvaluationReason;
1111
debugEventsUntilDate?: number;
1212
deleted?: boolean;
13+
prerequisites?: string[];
1314
}
1415

1516
export interface PatchFlag extends Flag {

packages/shared/sdk-server/__tests__/LDClient.allFlags.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,60 @@ describe('given an LDClient with test data', () => {
269269
done();
270270
});
271271
});
272+
273+
it('includes prerequisites in flag meta', async () => {
274+
await td.update(td.flag('is-prereq').valueForAll(true));
275+
await td.usePreconfiguredFlag({
276+
key: 'has-prereq-depth-1',
277+
on: true,
278+
prerequisites: [
279+
{
280+
key: 'is-prereq',
281+
variation: 0,
282+
},
283+
],
284+
fallthrough: {
285+
variation: 0,
286+
},
287+
offVariation: 1,
288+
variations: [true, false],
289+
clientSideAvailability: {
290+
usingMobileKey: true,
291+
usingEnvironmentId: true,
292+
},
293+
clientSide: true,
294+
version: 4,
295+
});
296+
297+
const state = await client.allFlagsState(defaultUser, {
298+
withReasons: true,
299+
detailsOnlyForTrackedFlags: false,
300+
});
301+
expect(state.valid).toEqual(true);
302+
expect(state.allValues()).toEqual({ 'is-prereq': true, 'has-prereq-depth-1': true });
303+
expect(state.toJSON()).toEqual({
304+
'is-prereq': true,
305+
'has-prereq-depth-1': true,
306+
$flagsState: {
307+
'is-prereq': {
308+
variation: 0,
309+
reason: {
310+
kind: 'FALLTHROUGH',
311+
},
312+
version: 1,
313+
},
314+
'has-prereq-depth-1': {
315+
variation: 0,
316+
prerequisites: ['is-prereq'],
317+
reason: {
318+
kind: 'FALLTHROUGH',
319+
},
320+
version: 4,
321+
},
322+
},
323+
$valid: true,
324+
});
325+
});
272326
});
273327

274328
describe('given an offline client', () => {

0 commit comments

Comments
 (0)