Skip to content

Commit f1972ba

Browse files
committed
Add a precomputed requestor test
1 parent 1df0647 commit f1972ba

File tree

2 files changed

+112
-1
lines changed

2 files changed

+112
-1
lines changed

src/precomputed-requestor.spec.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import ApiEndpoints from './api-endpoints';
2+
import { IConfigurationStore } from './configuration-store/configuration-store';
3+
import { MemoryOnlyConfigurationStore } from './configuration-store/memory.store';
4+
import FetchHttpClient, { IHttpClient } from './http-client';
5+
import { PrecomputedFlag } from './interfaces';
6+
import ConfigurationRequestor from './precomputed-requestor';
7+
8+
const MOCK_PRECOMPUTED_RESPONSE = {
9+
flags: {
10+
'precomputed-flag-1': {
11+
allocationKey: 'default',
12+
variationKey: 'true-variation',
13+
variationType: 'BOOLEAN',
14+
variationValue: 'true',
15+
extraLogging: {},
16+
doLog: true,
17+
},
18+
'precomputed-flag-2': {
19+
allocationKey: 'test-group',
20+
variationKey: 'variation-a',
21+
variationType: 'STRING',
22+
variationValue: 'variation-a',
23+
extraLogging: {},
24+
doLog: true,
25+
},
26+
},
27+
environment: 'production',
28+
createdAt: '2024-03-20T00:00:00Z',
29+
};
30+
31+
describe('PrecomputedRequestor', () => {
32+
let precomputedFlagStore: IConfigurationStore<PrecomputedFlag>;
33+
let httpClient: IHttpClient;
34+
let configurationRequestor: ConfigurationRequestor;
35+
let fetchSpy: jest.Mock;
36+
37+
beforeEach(() => {
38+
const apiEndpoints = new ApiEndpoints({
39+
baseUrl: 'http://127.0.0.1:4000',
40+
queryParams: {
41+
apiKey: 'dummy',
42+
sdkName: 'js-client-sdk-common',
43+
sdkVersion: '1.0.0',
44+
},
45+
});
46+
httpClient = new FetchHttpClient(apiEndpoints, 1000);
47+
precomputedFlagStore = new MemoryOnlyConfigurationStore<PrecomputedFlag>();
48+
configurationRequestor = new ConfigurationRequestor(httpClient, precomputedFlagStore);
49+
50+
fetchSpy = jest.fn(() => {
51+
return Promise.resolve({
52+
ok: true,
53+
status: 200,
54+
json: () => Promise.resolve(MOCK_PRECOMPUTED_RESPONSE),
55+
});
56+
}) as jest.Mock;
57+
global.fetch = fetchSpy;
58+
});
59+
60+
afterEach(() => {
61+
jest.clearAllMocks();
62+
});
63+
64+
afterAll(() => {
65+
jest.restoreAllMocks();
66+
});
67+
68+
describe('Precomputed flags', () => {
69+
it('Fetches and stores precomputed flag configuration', async () => {
70+
await configurationRequestor.fetchAndStorePrecomputedFlags();
71+
72+
expect(fetchSpy).toHaveBeenCalledTimes(1);
73+
74+
expect(precomputedFlagStore.getKeys().length).toBe(2);
75+
76+
const flag1 = precomputedFlagStore.get('precomputed-flag-1');
77+
expect(flag1?.allocationKey).toBe('default');
78+
expect(flag1?.variationKey).toBe('true-variation');
79+
expect(flag1?.variationType).toBe('BOOLEAN');
80+
expect(flag1?.variationValue).toBe('true');
81+
expect(flag1?.extraLogging).toEqual({});
82+
expect(flag1?.doLog).toBe(true);
83+
84+
const flag2 = precomputedFlagStore.get('precomputed-flag-2');
85+
expect(flag2?.allocationKey).toBe('test-group');
86+
expect(flag2?.variationKey).toBe('variation-a');
87+
expect(flag2?.variationType).toBe('STRING');
88+
expect(flag2?.variationValue).toBe('variation-a');
89+
expect(flag2?.extraLogging).toEqual({});
90+
expect(flag2?.doLog).toBe(true);
91+
92+
expect(precomputedFlagStore.getEnvironment()).toBe('production');
93+
expect(precomputedFlagStore.getConfigPublishedAt()).toBe('2024-03-20T00:00:00Z');
94+
});
95+
96+
it('Handles empty response gracefully', async () => {
97+
fetchSpy.mockImplementationOnce(() =>
98+
Promise.resolve({
99+
ok: true,
100+
status: 200,
101+
json: () => Promise.resolve({ flags: null }),
102+
}),
103+
);
104+
105+
await configurationRequestor.fetchAndStorePrecomputedFlags();
106+
107+
expect(fetchSpy).toHaveBeenCalledTimes(1);
108+
expect(precomputedFlagStore.getKeys().length).toBe(0);
109+
});
110+
});
111+
});

src/precomputed-requestor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { hydrateConfigurationStore } from './configuration-store/configuration-s
33
import { IHttpClient } from './http-client';
44
import { PrecomputedFlag } from './interfaces';
55

6-
// Requests AND stores flag configurations
6+
// Requests AND stores precomputed flags, reuses the configuration store
77
export default class ConfigurationRequestor {
88
constructor(
99
private readonly httpClient: IHttpClient,

0 commit comments

Comments
 (0)