Skip to content

Commit 98c3bc0

Browse files
committed
Add rudimentary tests for isolated instance
Signed-off-by: MattIPv4 <[email protected]>
1 parent ccc8bee commit 98c3bc0

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

packages/web/test/isolated.spec.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import type { JsonValue, OpenFeatureAPI, Provider, ProviderMetadata, ResolutionDetails } from '../src';
2+
3+
const GLOBAL_OPENFEATURE_API_KEY = Symbol.for('@openfeature/web-sdk/api');
4+
5+
class MockProvider implements Provider {
6+
readonly metadata: ProviderMetadata;
7+
8+
constructor(options?: { name?: string }) {
9+
this.metadata = { name: options?.name ?? 'mock-provider' };
10+
}
11+
12+
resolveBooleanEvaluation(): ResolutionDetails<boolean> {
13+
throw new Error('Not implemented');
14+
}
15+
16+
resolveNumberEvaluation(): ResolutionDetails<number> {
17+
throw new Error('Not implemented');
18+
}
19+
20+
resolveObjectEvaluation<T extends JsonValue>(): ResolutionDetails<T> {
21+
throw new Error('Not implemented');
22+
}
23+
24+
resolveStringEvaluation(): ResolutionDetails<string> {
25+
throw new Error('Not implemented');
26+
}
27+
}
28+
29+
const _globalThis = globalThis as {
30+
[GLOBAL_OPENFEATURE_API_KEY]?: OpenFeatureAPI;
31+
};
32+
33+
describe('OpenFeature', () => {
34+
beforeEach(() => {
35+
Reflect.deleteProperty(_globalThis, GLOBAL_OPENFEATURE_API_KEY);
36+
expect(_globalThis[GLOBAL_OPENFEATURE_API_KEY]).toBeUndefined();
37+
jest.resetModules();
38+
});
39+
40+
afterEach(async () => {
41+
jest.clearAllMocks();
42+
});
43+
44+
it('should persist via globalThis (window in browsers)', async () => {
45+
const firstInstance = (await import('../src')).OpenFeature;
46+
47+
jest.resetModules();
48+
const secondInstance = (await import('../src')).OpenFeature;
49+
50+
expect(firstInstance).toBe(secondInstance);
51+
expect(_globalThis[GLOBAL_OPENFEATURE_API_KEY]).toBe(firstInstance);
52+
});
53+
54+
describe('OpenFeature.isolated', () => {
55+
it('should not be the same instance as the global singleton', async () => {
56+
const { OpenFeature } = await import('../src');
57+
58+
expect(OpenFeature.isolated).not.toBe(OpenFeature);
59+
});
60+
61+
it('should not share state between global and isolated instances', async () => {
62+
const { OpenFeature, NOOP_PROVIDER } = await import('../src');
63+
const isolatedInstance = OpenFeature.isolated;
64+
65+
const globalProvider = new MockProvider({ name: 'global-provider' });
66+
OpenFeature.setProvider(globalProvider);
67+
68+
expect(OpenFeature.getProvider()).toBe(globalProvider);
69+
expect(isolatedInstance.getProvider()).toBe(NOOP_PROVIDER);
70+
71+
const isolatedProvider = new MockProvider({ name: 'isolated-provider' });
72+
isolatedInstance.setProvider(isolatedProvider);
73+
74+
expect(OpenFeature.getProvider()).toBe(globalProvider);
75+
expect(isolatedInstance.getProvider()).toBe(isolatedProvider);
76+
});
77+
78+
it('should persist when imported multiple times', async () => {
79+
const firstIsolatedInstance = (await import('../src')).OpenFeature.isolated;
80+
const secondIsolatedInstance = (await import('../src')).OpenFeature.isolated;
81+
82+
expect(firstIsolatedInstance).toBe(secondIsolatedInstance);
83+
});
84+
85+
it('should not persist via globalThis (window in browsers)', async () => {
86+
const firstIsolatedInstance = (await import('../src')).OpenFeature.isolated;
87+
88+
jest.resetModules();
89+
const secondIsolatedInstance = (await import('../src')).OpenFeature.isolated;
90+
91+
expect(firstIsolatedInstance).not.toBe(secondIsolatedInstance);
92+
});
93+
});
94+
});

packages/web/test/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
22
"extends": "../tsconfig.json",
33
"include": ["."],
4+
"compilerOptions": {
5+
"module": "es2020"
6+
}
47
}

0 commit comments

Comments
 (0)