Skip to content

Commit 427c025

Browse files
authored
Merge branch 'main' into ta/SDK-1318/run-fdv2-contract-tests-ci
2 parents d37d605 + 6b7bf7e commit 427c025

File tree

9 files changed

+482
-25
lines changed

9 files changed

+482
-25
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
import { integrations, LDContext, LDLogger } from '@launchdarkly/js-server-sdk-common';
2+
3+
import { LDOptions } from '../src/api/LDOptions';
4+
import { LDPlugin } from '../src/api/LDPlugin';
5+
import LDClientNode from '../src/LDClientNode';
6+
import NodeInfo from '../src/platform/NodeInfo';
7+
8+
// Test for plugin registration
9+
it('registers plugins and executes hooks during initialization', async () => {
10+
const logger: LDLogger = {
11+
debug: jest.fn(),
12+
info: jest.fn(),
13+
warn: jest.fn(),
14+
error: jest.fn(),
15+
};
16+
17+
const mockHook: integrations.Hook = {
18+
getMetadata(): integrations.HookMetadata {
19+
return {
20+
name: 'test-hook',
21+
};
22+
},
23+
beforeEvaluation: jest.fn(() => ({})),
24+
afterEvaluation: jest.fn(() => ({})),
25+
};
26+
27+
const mockPlugin: LDPlugin = {
28+
getMetadata: () => ({ name: 'test-plugin' }),
29+
register: jest.fn(),
30+
getHooks: () => [mockHook],
31+
};
32+
33+
const client = new LDClientNode('test', { offline: true, logger, plugins: [mockPlugin] });
34+
35+
// Verify the plugin was registered
36+
expect(mockPlugin.register).toHaveBeenCalled();
37+
38+
// Now test that hooks work by calling identify and variation
39+
const context: LDContext = { key: 'user-key', kind: 'user' };
40+
41+
await client.variation('flag-key', context, false);
42+
43+
expect(mockHook.beforeEvaluation).toHaveBeenCalledWith(
44+
{
45+
context,
46+
defaultValue: false,
47+
flagKey: 'flag-key',
48+
method: 'LDClient.variation',
49+
environmentId: undefined,
50+
},
51+
{},
52+
);
53+
54+
expect(mockHook.afterEvaluation).toHaveBeenCalled();
55+
});
56+
57+
// Test for multiple plugins with hooks
58+
it('registers multiple plugins and executes all hooks', async () => {
59+
const logger: LDLogger = {
60+
debug: jest.fn(),
61+
info: jest.fn(),
62+
warn: jest.fn(),
63+
error: jest.fn(),
64+
};
65+
66+
const mockHook1: integrations.Hook = {
67+
getMetadata(): integrations.HookMetadata {
68+
return {
69+
name: 'test-hook-1',
70+
};
71+
},
72+
beforeEvaluation: jest.fn(() => ({})),
73+
afterEvaluation: jest.fn(() => ({})),
74+
};
75+
76+
const mockHook2: integrations.Hook = {
77+
getMetadata(): integrations.HookMetadata {
78+
return {
79+
name: 'test-hook-2',
80+
};
81+
},
82+
beforeEvaluation: jest.fn(() => ({})),
83+
afterEvaluation: jest.fn(() => ({})),
84+
};
85+
86+
const mockPlugin1: LDPlugin = {
87+
getMetadata: () => ({ name: 'test-plugin-1' }),
88+
register: jest.fn(),
89+
getHooks: () => [mockHook1],
90+
};
91+
92+
const mockPlugin2: LDPlugin = {
93+
getMetadata: () => ({ name: 'test-plugin-2' }),
94+
register: jest.fn(),
95+
getHooks: () => [mockHook2],
96+
};
97+
98+
const client = new LDClientNode('test', {
99+
offline: true,
100+
logger,
101+
plugins: [mockPlugin1, mockPlugin2],
102+
});
103+
104+
// Verify plugins were registered
105+
expect(mockPlugin1.register).toHaveBeenCalled();
106+
expect(mockPlugin2.register).toHaveBeenCalled();
107+
108+
// Test that both hooks work
109+
const context: LDContext = { key: 'user-key', kind: 'user' };
110+
await client.variation('flag-key', context, false);
111+
112+
expect(mockHook1.beforeEvaluation).toHaveBeenCalled();
113+
expect(mockHook1.afterEvaluation).toHaveBeenCalled();
114+
expect(mockHook2.beforeEvaluation).toHaveBeenCalled();
115+
expect(mockHook2.afterEvaluation).toHaveBeenCalled();
116+
});
117+
118+
it('passes correct environmentMetadata to plugin getHooks and register functions', async () => {
119+
const logger: LDLogger = {
120+
debug: jest.fn(),
121+
info: jest.fn(),
122+
warn: jest.fn(),
123+
error: jest.fn(),
124+
};
125+
126+
const mockHook: integrations.Hook = {
127+
getMetadata(): integrations.HookMetadata {
128+
return {
129+
name: 'test-hook',
130+
};
131+
},
132+
beforeEvaluation: jest.fn(() => ({})),
133+
afterEvaluation: jest.fn(() => ({})),
134+
};
135+
136+
const mockPlugin: LDPlugin = {
137+
getMetadata: () => ({ name: 'test-plugin' }),
138+
register: jest.fn(),
139+
getHooks: jest.fn(() => [mockHook]),
140+
};
141+
142+
const options: LDOptions = {
143+
wrapperName: 'test-wrapper',
144+
wrapperVersion: '2.0.0',
145+
application: {
146+
id: 'test-app',
147+
name: 'TestApp',
148+
version: '3.0.0',
149+
versionName: '3',
150+
},
151+
offline: true,
152+
logger,
153+
plugins: [mockPlugin],
154+
};
155+
156+
// eslint-disable-next-line no-new
157+
new LDClientNode('test', options);
158+
const platformInfo = new NodeInfo(options);
159+
const sdkData = platformInfo.sdkData();
160+
expect(sdkData.name).toBeDefined();
161+
expect(sdkData.version).toBeDefined();
162+
163+
// Verify getHooks was called with correct environmentMetadata
164+
expect(mockPlugin.getHooks).toHaveBeenCalledWith({
165+
sdk: {
166+
name: sdkData.userAgentBase,
167+
version: sdkData.version,
168+
wrapperName: options.wrapperName,
169+
wrapperVersion: options.wrapperVersion,
170+
},
171+
application: {
172+
id: options.application?.id,
173+
name: options.application?.name,
174+
version: options.application?.version,
175+
versionName: options.application?.versionName,
176+
},
177+
sdkKey: 'test',
178+
});
179+
180+
// Verify register was called with correct environmentMetadata
181+
expect(mockPlugin.register).toHaveBeenCalledWith(
182+
expect.any(Object), // client
183+
{
184+
sdk: {
185+
name: sdkData.userAgentBase,
186+
version: sdkData.version,
187+
wrapperName: options.wrapperName,
188+
wrapperVersion: options.wrapperVersion,
189+
},
190+
application: {
191+
id: options.application?.id,
192+
version: options.application?.version,
193+
name: options.application?.name,
194+
versionName: options.application?.versionName,
195+
},
196+
sdkKey: 'test',
197+
},
198+
);
199+
});
200+
201+
it('passes correct environmentMetadata without optional fields', async () => {
202+
const logger: LDLogger = {
203+
debug: jest.fn(),
204+
info: jest.fn(),
205+
warn: jest.fn(),
206+
error: jest.fn(),
207+
};
208+
209+
const mockHook: integrations.Hook = {
210+
getMetadata(): integrations.HookMetadata {
211+
return {
212+
name: 'test-hook',
213+
};
214+
},
215+
beforeEvaluation: jest.fn(() => ({})),
216+
afterEvaluation: jest.fn(() => ({})),
217+
};
218+
219+
const mockPlugin: LDPlugin = {
220+
getMetadata: () => ({ name: 'test-plugin' }),
221+
register: jest.fn(),
222+
getHooks: jest.fn(() => [mockHook]),
223+
};
224+
225+
const options: LDOptions = {
226+
offline: true,
227+
logger,
228+
plugins: [mockPlugin],
229+
};
230+
231+
// eslint-disable-next-line no-new
232+
new LDClientNode('test', options);
233+
234+
const platformInfo = new NodeInfo(options);
235+
const sdkData = platformInfo.sdkData();
236+
expect(sdkData.name).toBeDefined();
237+
expect(sdkData.version).toBeDefined();
238+
239+
// Verify getHooks was called with correct environmentMetadata
240+
expect(mockPlugin.getHooks).toHaveBeenCalledWith({
241+
sdk: {
242+
name: sdkData.userAgentBase,
243+
version: sdkData.version,
244+
},
245+
sdkKey: 'test',
246+
});
247+
248+
// Verify register was called with correct environmentMetadata
249+
expect(mockPlugin.register).toHaveBeenCalledWith(
250+
expect.any(Object), // client
251+
{
252+
sdk: {
253+
name: sdkData.userAgentBase,
254+
version: sdkData.version,
255+
},
256+
sdkKey: 'test',
257+
},
258+
);
259+
});

0 commit comments

Comments
 (0)