Skip to content

Commit d1aa010

Browse files
Add test for data collector
Signed-off-by: Thomas Poignant <[email protected]>
1 parent 9a95905 commit d1aa010

File tree

1 file changed

+131
-18
lines changed

1 file changed

+131
-18
lines changed

libs/providers/go-feature-flag/src/lib/go-feature-flag-provider.spec.ts

+131-18
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,33 @@ import {GoFeatureFlagProxyResponse} from './model';
1818

1919
describe('GoFeatureFlagProvider', () => {
2020
const endpoint = 'http://go-feature-flag-relay-proxy.local:1031/';
21+
const dataCollectorEndpoint = `${endpoint}v1/data/collector`;
2122
const axiosMock = new MockAdapter(axios);
23+
const validBoolResponse: GoFeatureFlagProxyResponse<boolean> = {
24+
value: true,
25+
variationType: 'trueVariation',
26+
reason: StandardResolutionReasons.TARGETING_MATCH,
27+
failed: false,
28+
trackEvents: true,
29+
version: '1.0.0',
30+
metadata: {
31+
description: 'a description of the flag',
32+
issue_number: 1,
33+
},
34+
cacheable: true,
35+
};
2236
let goff: GoFeatureFlagProvider;
2337

2438
afterEach(async () => {
25-
axiosMock.reset();
26-
axiosMock.resetHistory();
27-
axiosMock.resetHandlers()
2839
await OpenFeature.close();
40+
await axiosMock.reset();
41+
await axiosMock.resetHistory();
2942
});
3043

31-
beforeEach(() => {
44+
beforeEach(async () => {
45+
await OpenFeature.close();
46+
await axiosMock.reset();
47+
await axiosMock.resetHistory();
3248
goff = new GoFeatureFlagProvider({endpoint});
3349
});
3450

@@ -663,20 +679,6 @@ describe('GoFeatureFlagProvider', () => {
663679
});
664680
});
665681
describe('cache testing', () => {
666-
const validBoolResponse: GoFeatureFlagProxyResponse<boolean> = {
667-
value: true,
668-
variationType: 'trueVariation',
669-
reason: StandardResolutionReasons.TARGETING_MATCH,
670-
failed: false,
671-
trackEvents: true,
672-
version: '1.0.0',
673-
metadata: {
674-
description: 'a description of the flag',
675-
issue_number: 1,
676-
},
677-
cacheable: true,
678-
};
679-
680682
it('should use the cache if we evaluate 2 times the same flag', async () => {
681683
const flagName = 'random-flag';
682684
const targetingKey = 'user-key';
@@ -793,4 +795,115 @@ describe('GoFeatureFlagProvider', () => {
793795
expect(axiosMock.history['post'].length).toBe(2);
794796
});
795797
});
798+
describe('data collector testing', () => {
799+
it('should call the data collector when closing Open Feature', async () => {
800+
const flagName = 'random-flag';
801+
const targetingKey = 'user-key';
802+
const dns = `${endpoint}v1/feature/${flagName}/eval`;
803+
804+
axiosMock.onPost(dns).reply(200, validBoolResponse);
805+
const goff = new GoFeatureFlagProvider({
806+
endpoint,
807+
flagCacheTTL: 3000,
808+
flagCacheSize: 100,
809+
dataFlushInterval: 1000, // in milliseconds
810+
})
811+
const providerName = expect.getState().currentTestName || 'test';
812+
OpenFeature.setProvider(providerName, goff);
813+
const cli = OpenFeature.getClient(providerName);
814+
await cli.getBooleanDetails(flagName, false, {targetingKey});
815+
await cli.getBooleanDetails(flagName, false, {targetingKey});
816+
await OpenFeature.close()
817+
const collectorCalls = axiosMock.history['post'].filter(i => i.url === dataCollectorEndpoint);
818+
expect(collectorCalls.length).toBe(1);
819+
const got = JSON.parse(collectorCalls[0].data);
820+
expect(isNaN(got.events[0].creationDate)).toBe(false);
821+
const want = {
822+
events: [{
823+
contextKind: 'user',
824+
kind: 'feature',
825+
creationDate: got.events[0].creationDate,
826+
default: false,
827+
key: 'random-flag',
828+
value: true,
829+
variation: 'trueVariation',
830+
userKey: 'user-key'
831+
}], meta: {provider: 'open-feature-js-sdk'}
832+
};
833+
expect(want).toEqual(got);
834+
});
835+
836+
it('should call the data collector when waiting more than the dataFlushInterval', async () => {
837+
const flagName = 'random-flag';
838+
const targetingKey = 'user-key';
839+
const dns = `${endpoint}v1/feature/${flagName}/eval`;
840+
841+
axiosMock.onPost(dns).reply(200, validBoolResponse);
842+
const goff = new GoFeatureFlagProvider({
843+
endpoint,
844+
flagCacheTTL: 3000,
845+
flagCacheSize: 100,
846+
dataFlushInterval: 100, // in milliseconds
847+
})
848+
const providerName = expect.getState().currentTestName || 'test';
849+
OpenFeature.setProvider(providerName, goff);
850+
const cli = OpenFeature.getClient(providerName);
851+
await cli.getBooleanDetails(flagName, false, {targetingKey});
852+
await cli.getBooleanDetails(flagName, false, {targetingKey});
853+
await new Promise((r) => setTimeout(r, 130));
854+
const collectorCalls = axiosMock.history['post'].filter(i => i.url === dataCollectorEndpoint);
855+
expect(collectorCalls.length).toBe(1);
856+
});
857+
858+
it('should call the data collector multiple time while waiting dataFlushInterval time', async () => {
859+
const flagName = 'random-flag';
860+
const targetingKey = 'user-key';
861+
const dns = `${endpoint}v1/feature/${flagName}/eval`;
862+
863+
axiosMock.onPost(dns).reply(200, validBoolResponse);
864+
const goff = new GoFeatureFlagProvider({
865+
endpoint,
866+
flagCacheTTL: 3000,
867+
flagCacheSize: 100,
868+
dataFlushInterval: 100, // in milliseconds
869+
})
870+
const providerName = expect.getState().currentTestName || 'test';
871+
OpenFeature.setProvider(providerName, goff);
872+
const cli = OpenFeature.getClient(providerName);
873+
await cli.getBooleanDetails(flagName, false, {targetingKey});
874+
await cli.getBooleanDetails(flagName, false, {targetingKey});
875+
await new Promise((r) => setTimeout(r, 130));
876+
const collectorCalls = axiosMock.history['post'].filter(i => i.url === dataCollectorEndpoint);
877+
expect(collectorCalls.length).toBe(1);
878+
axiosMock.resetHistory();
879+
await cli.getBooleanDetails(flagName, false, {targetingKey});
880+
await cli.getBooleanDetails(flagName, false, {targetingKey});
881+
await new Promise((r) => setTimeout(r, 130));
882+
const collectorCalls2 = axiosMock.history['post'].filter(i => i.url === dataCollectorEndpoint);
883+
expect(collectorCalls2.length).toBe(1);
884+
});
885+
886+
it('should not call the data collector before the dataFlushInterval', async () => {
887+
const flagName = 'random-flag';
888+
const targetingKey = 'user-key';
889+
const dns = `${endpoint}v1/feature/${flagName}/eval`;
890+
891+
axiosMock.onPost(dns).reply(200, validBoolResponse);
892+
const goff = new GoFeatureFlagProvider({
893+
endpoint,
894+
flagCacheTTL: 3000,
895+
flagCacheSize: 100,
896+
dataFlushInterval: 200, // in milliseconds
897+
})
898+
const providerName = expect.getState().currentTestName || 'test';
899+
OpenFeature.setProvider(providerName, goff);
900+
const cli = OpenFeature.getClient(providerName);
901+
await cli.getBooleanDetails(flagName, false, {targetingKey});
902+
await cli.getBooleanDetails(flagName, false, {targetingKey});
903+
await new Promise((r) => setTimeout(r, 130));
904+
const collectorCalls = axiosMock.history['post'].filter(i => i.url === dataCollectorEndpoint);
905+
906+
expect(collectorCalls.length).toBe(0);
907+
});
908+
});
796909
});

0 commit comments

Comments
 (0)