Skip to content

Commit 618f9ea

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

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

packages/web/test/isolated.spec.ts

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

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)