@envive-ai/react-hooks 0.3.58 → 0.3.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/commerce-api.cjs +1 -1
- package/dist/application/commerce-api.js +1 -1
- package/dist/application/models/graphql/index.cjs +0 -4
- package/dist/application/models/graphql/index.d.cts +2 -3
- package/dist/application/models/graphql/index.d.ts +2 -3
- package/dist/application/models/graphql/index.js +1 -3
- package/dist/application/models/graphql/queries/getMerchantColorsQuery.d.cts +2 -3
- package/dist/application/models/graphql/queries/getMerchantColorsQuery.d.ts +2 -3
- package/dist/application/models/graphql/queries/getWidgetConfigQuery.cjs +22 -3
- package/dist/application/models/graphql/queries/getWidgetConfigQuery.js +22 -3
- package/dist/application/models/index.cjs +0 -4
- package/dist/application/models/index.d.cts +2 -3
- package/dist/application/models/index.d.ts +2 -3
- package/dist/application/models/index.js +1 -3
- package/dist/application/utils/elementObserver.d.cts +2 -2
- package/dist/application/utils/index.cjs +1 -1
- package/dist/application/utils/index.js +1 -1
- package/dist/atoms/app/index.d.cts +7 -7
- package/dist/atoms/app/index.d.ts +7 -7
- package/dist/atoms/chat/chatState.d.cts +18 -18
- package/dist/atoms/chat/chatState.d.ts +19 -19
- package/dist/atoms/chat/form.d.cts +2 -2
- package/dist/atoms/chat/form.d.ts +2 -2
- package/dist/atoms/chat/index.d.cts +2 -2
- package/dist/atoms/chat/index.d.ts +2 -2
- package/dist/atoms/chat/lastMessage.d.cts +2 -2
- package/dist/atoms/chat/lastMessage.d.ts +2 -2
- package/dist/atoms/chat/messageQueue.d.cts +6 -6
- package/dist/atoms/chat/messageQueue.d.ts +6 -6
- package/dist/atoms/chat/performanceMetrics.d.cts +6 -6
- package/dist/atoms/chat/performanceMetrics.d.ts +6 -6
- package/dist/atoms/chat/renderedWidgetRefs.d.cts +2 -2
- package/dist/atoms/chat/renderedWidgetRefs.d.ts +2 -2
- package/dist/atoms/chat/replies.d.cts +3 -3
- package/dist/atoms/chat/replies.d.ts +2 -2
- package/dist/atoms/chat/suggestions.d.cts +2 -2
- package/dist/atoms/chat/suggestions.d.ts +2 -2
- package/dist/atoms/envive/enviveConfig.d.ts +14 -14
- package/dist/atoms/globalSearch/globalSearch.d.cts +5 -5
- package/dist/atoms/globalSearch/globalSearch.d.ts +5 -5
- package/dist/atoms/org/customerService.d.cts +6 -6
- package/dist/atoms/org/customerService.d.ts +6 -6
- package/dist/atoms/org/graphqlConfig.d.cts +4 -4
- package/dist/atoms/org/graphqlConfig.d.ts +4 -4
- package/dist/atoms/org/newOrgConfigAtom.d.cts +2 -2
- package/dist/atoms/org/newOrgConfigAtom.d.ts +2 -2
- package/dist/atoms/org/orgAnalyticsConfig.d.cts +4 -4
- package/dist/atoms/org/orgAnalyticsConfig.d.ts +4 -4
- package/dist/atoms/search/chatSearch.d.cts +17 -17
- package/dist/atoms/search/chatSearch.d.ts +17 -17
- package/dist/atoms/search/searchAPI.d.cts +13 -13
- package/dist/atoms/search/searchAPI.d.ts +13 -13
- package/dist/atoms/search/types.d.cts +1 -1
- package/dist/atoms/widget/chatPreviewLoading.d.cts +2 -2
- package/dist/atoms/widget/chatPreviewLoading.d.ts +2 -2
- package/dist/contexts/pageContext/pageContext.cjs +1 -1
- package/dist/contexts/pageContext/pageContext.js +1 -1
- package/dist/contexts/systemSettingsContext/systemSettingsContext.d.cts +2 -2
- package/dist/contexts/types.d.cts +1 -1
- package/dist/contexts/types.d.ts +1 -1
- package/dist/contexts/typesV3.d.cts +1 -1
- package/dist/contexts/typesV3.d.ts +1 -1
- package/dist/contexts/widgetConfigContext/widgetConfigContext.cjs +22 -31
- package/dist/contexts/widgetConfigContext/widgetConfigContext.js +22 -31
- package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.cts +2 -2
- package/dist/hooks/GrabAndScroll/useGrabAndScroll.d.ts +2 -2
- package/dist/hooks/Intersection/useIntersection.cjs +14 -3
- package/dist/hooks/Intersection/useIntersection.js +14 -3
- package/dist/hooks/PageViewedEvent/usePageViewedEvent.cjs +1 -1
- package/dist/hooks/PageViewedEvent/usePageViewedEvent.js +1 -1
- package/dist/hooks/SystemSettingsContext/useSystemSettingsContext.d.cts +2 -2
- package/dist/hooks/utils.d.ts +1 -1
- package/dist/services/enviveConfigService/enviveConfigService.cjs +3 -24
- package/dist/services/enviveConfigService/enviveConfigService.js +4 -25
- package/dist/services/enviveConfigService/fetchGraphQLConfig.cjs +59 -54
- package/dist/services/enviveConfigService/fetchGraphQLConfig.js +60 -54
- package/dist/services/hardcopyService/hardcopyService.cjs +1 -1
- package/dist/services/hardcopyService/hardcopyService.js +1 -1
- package/dist/types/config-versions.cjs +1 -3
- package/dist/types/config-versions.js +2 -3
- package/package.json +1 -1
- package/src/application/models/graphql/index.ts +0 -1
- package/src/application/models/graphql/queries/getMerchantColorsQuery.ts +4 -15
- package/src/application/models/graphql/queries/getWidgetConfigQuery.ts +35 -14
- package/src/application/models/index.ts +0 -1
- package/src/contexts/pageContext/__tests__/pageContext.test.tsx +1 -2
- package/src/contexts/pageContext/pageContext.tsx +1 -2
- package/src/contexts/widgetConfigContext/__tests__/widgetConfigContext.test.tsx +52 -0
- package/src/contexts/widgetConfigContext/widgetConfigContext.tsx +39 -36
- package/src/hooks/Intersection/__tests__/useIntersection.test.ts +134 -0
- package/src/hooks/Intersection/useIntersection.ts +20 -4
- package/src/services/enviveConfigService/__tests__/enviveConfigService.test.ts +51 -75
- package/src/services/enviveConfigService/__tests__/fetchGraphQLConfig.test.ts +242 -90
- package/src/services/enviveConfigService/enviveConfigService.ts +15 -41
- package/src/services/enviveConfigService/fetchGraphQLConfig.ts +106 -68
- package/dist/application/models/graphql/queries/getColorsAndFrontendQuery.cjs +0 -18
- package/dist/application/models/graphql/queries/getColorsAndFrontendQuery.js +0 -18
- package/dist/application/models/graphql/queries/getMerchantColorsQuery.cjs +0 -18
- package/dist/application/models/graphql/queries/getMerchantColorsQuery.js +0 -18
- package/dist/application/models/graphql/queries/getMerchantFrontendConfigQuery.cjs +0 -18
- package/dist/application/models/graphql/queries/getMerchantFrontendConfigQuery.d.cts +0 -75
- package/dist/application/models/graphql/queries/getMerchantFrontendConfigQuery.d.ts +0 -75
- package/dist/application/models/graphql/queries/getMerchantFrontendConfigQuery.js +0 -18
- package/src/application/models/graphql/queries/getColorsAndFrontendQuery.ts +0 -13
- package/src/application/models/graphql/queries/getMerchantFrontendConfigQuery.ts +0 -103
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { mockV3ColorsConfig, mockV3FrontendConfig } from 'src/contexts/graphqlContext/mockV3Config';
|
|
2
2
|
import { FloatingButtonLocation } from '@envive-ai/react-toolkit-v3/FloatingButton';
|
|
3
|
-
import {
|
|
4
|
-
DEFAULT_PAGE_VARIANTS,
|
|
5
|
-
fetchGraphQLConfig,
|
|
6
|
-
fetchUnifiedGraphQLConfig,
|
|
7
|
-
} from '../fetchGraphQLConfig';
|
|
3
|
+
import { DEFAULT_PAGE_VARIANTS, fetchUnifiedGraphQLConfig } from '../fetchGraphQLConfig';
|
|
8
4
|
|
|
9
5
|
const { MockLogger } = vi.hoisted(() => {
|
|
10
6
|
const MockLogger = vi.fn(function () {
|
|
@@ -25,9 +21,11 @@ function makeOkFetch(v3RootConfigValues: unknown, frontendValues?: unknown) {
|
|
|
25
21
|
Promise.resolve({
|
|
26
22
|
data: {
|
|
27
23
|
me: {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
getWidgetConfig: {
|
|
25
|
+
productsConfig: {
|
|
26
|
+
v_three_config: { values: v3RootConfigValues },
|
|
27
|
+
frontend: frontendValues == null ? undefined : { values: frontendValues },
|
|
28
|
+
},
|
|
31
29
|
},
|
|
32
30
|
},
|
|
33
31
|
},
|
|
@@ -59,33 +57,33 @@ beforeEach(() => {
|
|
|
59
57
|
vi.clearAllMocks();
|
|
60
58
|
});
|
|
61
59
|
|
|
62
|
-
describe('
|
|
60
|
+
describe('productsConfig transform (via getWidgetConfig)', () => {
|
|
63
61
|
describe('error handling', () => {
|
|
64
|
-
it('
|
|
62
|
+
it('throws when the HTTP response is not ok', async () => {
|
|
65
63
|
mockFetch.mockResolvedValueOnce({ ok: false, statusText: 'Unauthorized' });
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
await expect(
|
|
66
|
+
fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app'),
|
|
67
|
+
).rejects.toThrow('Unified config request failed');
|
|
70
68
|
});
|
|
71
69
|
|
|
72
|
-
it('
|
|
70
|
+
it('throws when the response contains GraphQL errors', async () => {
|
|
73
71
|
mockFetch.mockResolvedValueOnce({
|
|
74
72
|
ok: true,
|
|
75
73
|
json: () => Promise.resolve({ errors: [{ message: 'Not authorized' }], data: null }),
|
|
76
74
|
});
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
await expect(
|
|
77
|
+
fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app'),
|
|
78
|
+
).rejects.toThrow('Unified config GraphQL errors');
|
|
81
79
|
});
|
|
82
80
|
|
|
83
|
-
it('
|
|
81
|
+
it('propagates the error when fetch throws', async () => {
|
|
84
82
|
mockFetch.mockRejectedValueOnce(new Error('Network failure'));
|
|
85
83
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
await expect(
|
|
85
|
+
fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app'),
|
|
86
|
+
).rejects.toThrow('Network failure');
|
|
89
87
|
});
|
|
90
88
|
});
|
|
91
89
|
|
|
@@ -93,9 +91,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
93
91
|
it('returns mock config when v3RootConfig has no colors field', async () => {
|
|
94
92
|
makeOkFetch({ ui_configs: {} });
|
|
95
93
|
|
|
96
|
-
const result = await
|
|
94
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
95
|
+
'https://api.example.com',
|
|
96
|
+
'key',
|
|
97
|
+
'user_1',
|
|
98
|
+
[],
|
|
99
|
+
'app',
|
|
100
|
+
);
|
|
97
101
|
|
|
98
|
-
expect(result).toEqual({
|
|
102
|
+
expect(result.orgConfig).toEqual({
|
|
99
103
|
colorsConfig: mockV3ColorsConfig,
|
|
100
104
|
frontendConfig: mockV3FrontendConfig,
|
|
101
105
|
orgPageConfig: {
|
|
@@ -111,13 +115,19 @@ describe('fetchGraphQLConfig', () => {
|
|
|
111
115
|
ok: true,
|
|
112
116
|
json: () =>
|
|
113
117
|
Promise.resolve({
|
|
114
|
-
data: { me: {
|
|
118
|
+
data: { me: { getWidgetConfig: { productsConfig: {} } } },
|
|
115
119
|
}),
|
|
116
120
|
});
|
|
117
121
|
|
|
118
|
-
const result = await
|
|
122
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
123
|
+
'https://api.example.com',
|
|
124
|
+
'key',
|
|
125
|
+
'user_1',
|
|
126
|
+
[],
|
|
127
|
+
'app',
|
|
128
|
+
);
|
|
119
129
|
|
|
120
|
-
expect(result).toEqual({
|
|
130
|
+
expect(result.orgConfig).toEqual({
|
|
121
131
|
colorsConfig: mockV3ColorsConfig,
|
|
122
132
|
frontendConfig: mockV3FrontendConfig,
|
|
123
133
|
orgPageConfig: {
|
|
@@ -141,9 +151,17 @@ describe('fetchGraphQLConfig', () => {
|
|
|
141
151
|
ui_configs: { ...baseV3Config.ui_configs, floating_button: { position } },
|
|
142
152
|
});
|
|
143
153
|
|
|
144
|
-
const result = await
|
|
154
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
155
|
+
'https://api.example.com',
|
|
156
|
+
'key',
|
|
157
|
+
'user_1',
|
|
158
|
+
[],
|
|
159
|
+
'app',
|
|
160
|
+
);
|
|
145
161
|
|
|
146
|
-
expect((result.frontendConfig as any)?.uiConfigs?.floatingButton?.position).toBe(
|
|
162
|
+
expect((result.orgConfig?.frontendConfig as any)?.uiConfigs?.floatingButton?.position).toBe(
|
|
163
|
+
expected,
|
|
164
|
+
);
|
|
147
165
|
});
|
|
148
166
|
|
|
149
167
|
it('returns empty config for an unrecognised position string', async () => {
|
|
@@ -152,9 +170,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
152
170
|
ui_configs: { ...baseV3Config.ui_configs, floating_button: { position: 'top-center' } },
|
|
153
171
|
});
|
|
154
172
|
|
|
155
|
-
const result = await
|
|
173
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
174
|
+
'https://api.example.com',
|
|
175
|
+
'key',
|
|
176
|
+
'user_1',
|
|
177
|
+
[],
|
|
178
|
+
'app',
|
|
179
|
+
);
|
|
156
180
|
|
|
157
|
-
expect(result).toEqual({ colorsConfig: undefined, frontendConfig: undefined });
|
|
181
|
+
expect(result.orgConfig).toEqual({ colorsConfig: undefined, frontendConfig: undefined });
|
|
158
182
|
});
|
|
159
183
|
});
|
|
160
184
|
|
|
@@ -174,8 +198,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
174
198
|
},
|
|
175
199
|
});
|
|
176
200
|
|
|
177
|
-
const result = await
|
|
178
|
-
|
|
201
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
202
|
+
'https://api.example.com',
|
|
203
|
+
'key',
|
|
204
|
+
'user_1',
|
|
205
|
+
[],
|
|
206
|
+
'app',
|
|
207
|
+
);
|
|
208
|
+
const fontSize = (result.orgConfig?.frontendConfig as any)?.uiConfigs?.lookAndFeel?.typography
|
|
209
|
+
?.fontSize;
|
|
179
210
|
|
|
180
211
|
expect(fontSize?.b1).toBe('14px');
|
|
181
212
|
expect(fontSize?.h1).toBe('20px');
|
|
@@ -196,9 +227,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
196
227
|
},
|
|
197
228
|
});
|
|
198
229
|
|
|
199
|
-
const result = await
|
|
200
|
-
|
|
201
|
-
|
|
230
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
231
|
+
'https://api.example.com',
|
|
232
|
+
'key',
|
|
233
|
+
'user_1',
|
|
234
|
+
[],
|
|
235
|
+
'app',
|
|
236
|
+
);
|
|
237
|
+
const lineHeight = (result.orgConfig?.frontendConfig as any)?.uiConfigs?.lookAndFeel
|
|
238
|
+
?.typography?.lineHeight;
|
|
202
239
|
|
|
203
240
|
expect(lineHeight?.['114']).toBe('1.14');
|
|
204
241
|
expect(lineHeight?.['128']).toBe('1.28');
|
|
@@ -220,8 +257,14 @@ describe('fetchGraphQLConfig', () => {
|
|
|
220
257
|
},
|
|
221
258
|
});
|
|
222
259
|
|
|
223
|
-
const result = await
|
|
224
|
-
|
|
260
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
261
|
+
'https://api.example.com',
|
|
262
|
+
'key',
|
|
263
|
+
'user_1',
|
|
264
|
+
[],
|
|
265
|
+
'app',
|
|
266
|
+
);
|
|
267
|
+
const lookAndFeel = (result.orgConfig?.frontendConfig as any)?.uiConfigs?.lookAndFeel;
|
|
225
268
|
|
|
226
269
|
expect(lookAndFeel?.chatHeaderLogoDarkSrc).toBe('logo.png');
|
|
227
270
|
});
|
|
@@ -240,8 +283,14 @@ describe('fetchGraphQLConfig', () => {
|
|
|
240
283
|
},
|
|
241
284
|
});
|
|
242
285
|
|
|
243
|
-
const result = await
|
|
244
|
-
|
|
286
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
287
|
+
'https://api.example.com',
|
|
288
|
+
'key',
|
|
289
|
+
'user_1',
|
|
290
|
+
[],
|
|
291
|
+
'app',
|
|
292
|
+
);
|
|
293
|
+
const lookAndFeel = (result.orgConfig?.frontendConfig as any)?.uiConfigs?.lookAndFeel;
|
|
245
294
|
|
|
246
295
|
expect(lookAndFeel?.chatHeaderLogoLightSrc).toBe('logo.png');
|
|
247
296
|
});
|
|
@@ -249,8 +298,14 @@ describe('fetchGraphQLConfig', () => {
|
|
|
249
298
|
it('uses explicit dark/light src when both are set', async () => {
|
|
250
299
|
makeOkFetch(baseV3Config);
|
|
251
300
|
|
|
252
|
-
const result = await
|
|
253
|
-
|
|
301
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
302
|
+
'https://api.example.com',
|
|
303
|
+
'key',
|
|
304
|
+
'user_1',
|
|
305
|
+
[],
|
|
306
|
+
'app',
|
|
307
|
+
);
|
|
308
|
+
const lookAndFeel = (result.orgConfig?.frontendConfig as any)?.uiConfigs?.lookAndFeel;
|
|
254
309
|
|
|
255
310
|
expect(lookAndFeel?.chatHeaderLogoDarkSrc).toBe('logo-dark.png');
|
|
256
311
|
expect(lookAndFeel?.chatHeaderLogoLightSrc).toBe('logo-light.png');
|
|
@@ -267,17 +322,33 @@ describe('fetchGraphQLConfig', () => {
|
|
|
267
322
|
},
|
|
268
323
|
});
|
|
269
324
|
|
|
270
|
-
const result = await
|
|
325
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
326
|
+
'https://api.example.com',
|
|
327
|
+
'key',
|
|
328
|
+
'user_1',
|
|
329
|
+
[],
|
|
330
|
+
'app',
|
|
331
|
+
);
|
|
271
332
|
|
|
272
|
-
expect((result.frontendConfig as any)?.merchantOverrideCss).toBe(
|
|
333
|
+
expect((result.orgConfig?.frontendConfig as any)?.merchantOverrideCss).toBe(
|
|
334
|
+
'body { color: red; }',
|
|
335
|
+
);
|
|
273
336
|
});
|
|
274
337
|
|
|
275
338
|
it('falls back to frontendValues.merchant_override_css when absent from v3 config', async () => {
|
|
276
339
|
makeOkFetch(baseV3Config, { merchant_override_css: 'body { color: blue; }' });
|
|
277
340
|
|
|
278
|
-
const result = await
|
|
341
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
342
|
+
'https://api.example.com',
|
|
343
|
+
'key',
|
|
344
|
+
'user_1',
|
|
345
|
+
[],
|
|
346
|
+
'app',
|
|
347
|
+
);
|
|
279
348
|
|
|
280
|
-
expect((result.frontendConfig as any)?.merchantOverrideCss).toBe(
|
|
349
|
+
expect((result.orgConfig?.frontendConfig as any)?.merchantOverrideCss).toBe(
|
|
350
|
+
'body { color: blue; }',
|
|
351
|
+
);
|
|
281
352
|
});
|
|
282
353
|
});
|
|
283
354
|
|
|
@@ -285,9 +356,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
285
356
|
it('uses DEFAULT_PAGE_VARIANTS when page_variants is not an array', async () => {
|
|
286
357
|
makeOkFetch({ ...baseV3Config, page_variants: null });
|
|
287
358
|
|
|
288
|
-
const result = await
|
|
359
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
360
|
+
'https://api.example.com',
|
|
361
|
+
'key',
|
|
362
|
+
'user_1',
|
|
363
|
+
[],
|
|
364
|
+
'app',
|
|
365
|
+
);
|
|
289
366
|
|
|
290
|
-
expect(result.orgPageConfig?.pageVariants).toEqual(DEFAULT_PAGE_VARIANTS);
|
|
367
|
+
expect(result.orgConfig?.orgPageConfig?.pageVariants).toEqual(DEFAULT_PAGE_VARIANTS);
|
|
291
368
|
});
|
|
292
369
|
|
|
293
370
|
it('transforms each page variant entry from the API response', async () => {
|
|
@@ -300,11 +377,19 @@ describe('fetchGraphQLConfig', () => {
|
|
|
300
377
|
};
|
|
301
378
|
makeOkFetch({ ...baseV3Config, page_variants: [rawVariant] });
|
|
302
379
|
|
|
303
|
-
const result = await
|
|
380
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
381
|
+
'https://api.example.com',
|
|
382
|
+
'key',
|
|
383
|
+
'user_1',
|
|
384
|
+
[],
|
|
385
|
+
'app',
|
|
386
|
+
);
|
|
304
387
|
|
|
305
|
-
expect(result.orgPageConfig?.pageVariants).toHaveLength(1);
|
|
306
|
-
expect(result.orgPageConfig?.pageVariants[0].variantId).toBe('plp');
|
|
307
|
-
expect(result.orgPageConfig?.pageVariants[0].variantTests?.[0].testType).toBe(
|
|
388
|
+
expect(result.orgConfig?.orgPageConfig?.pageVariants).toHaveLength(1);
|
|
389
|
+
expect(result.orgConfig?.orgPageConfig?.pageVariants[0].variantId).toBe('plp');
|
|
390
|
+
expect(result.orgConfig?.orgPageConfig?.pageVariants[0].variantTests?.[0].testType).toBe(
|
|
391
|
+
'UrlResolver',
|
|
392
|
+
);
|
|
308
393
|
});
|
|
309
394
|
});
|
|
310
395
|
|
|
@@ -316,24 +401,36 @@ describe('fetchGraphQLConfig', () => {
|
|
|
316
401
|
];
|
|
317
402
|
makeOkFetch({ ...baseV3Config, widget_configs: rawWidgets });
|
|
318
403
|
|
|
319
|
-
const result = await
|
|
404
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
405
|
+
'https://api.example.com',
|
|
406
|
+
'key',
|
|
407
|
+
'user_1',
|
|
408
|
+
[],
|
|
409
|
+
'app',
|
|
410
|
+
);
|
|
320
411
|
|
|
321
|
-
expect(Object.keys(result.orgPageConfig?.widgetConfigs ?? {})).toEqual([
|
|
412
|
+
expect(Object.keys(result.orgConfig?.orgPageConfig?.widgetConfigs ?? {})).toEqual([
|
|
322
413
|
'widget-1',
|
|
323
414
|
'widget-2',
|
|
324
415
|
]);
|
|
325
|
-
expect(
|
|
326
|
-
'widget-1',
|
|
327
|
-
);
|
|
416
|
+
expect(
|
|
417
|
+
(result.orgConfig?.orgPageConfig?.widgetConfigs as any)?.['widget-1']?.widgetConfigId,
|
|
418
|
+
).toBe('widget-1');
|
|
328
419
|
});
|
|
329
420
|
|
|
330
421
|
it('also exposes widget configs on frontendConfig', async () => {
|
|
331
422
|
const rawWidgets = [{ widget_config_id: 'widget-1', widget_type: 'floating_button' }];
|
|
332
423
|
makeOkFetch({ ...baseV3Config, widget_configs: rawWidgets });
|
|
333
424
|
|
|
334
|
-
const result = await
|
|
425
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
426
|
+
'https://api.example.com',
|
|
427
|
+
'key',
|
|
428
|
+
'user_1',
|
|
429
|
+
[],
|
|
430
|
+
'app',
|
|
431
|
+
);
|
|
335
432
|
|
|
336
|
-
expect((result.frontendConfig as any)?.widgetConfigs?.['widget-1']).toBeDefined();
|
|
433
|
+
expect((result.orgConfig?.frontendConfig as any)?.widgetConfigs?.['widget-1']).toBeDefined();
|
|
337
434
|
});
|
|
338
435
|
});
|
|
339
436
|
|
|
@@ -352,10 +449,18 @@ describe('fetchGraphQLConfig', () => {
|
|
|
352
449
|
];
|
|
353
450
|
makeOkFetch({ ...baseV3Config, mounting_configs: rawMountingConfigs });
|
|
354
451
|
|
|
355
|
-
const result = await
|
|
452
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
453
|
+
'https://api.example.com',
|
|
454
|
+
'key',
|
|
455
|
+
'user_1',
|
|
456
|
+
[],
|
|
457
|
+
'app',
|
|
458
|
+
);
|
|
356
459
|
|
|
357
|
-
expect(result.orgPageConfig?.mountingConfigs?.['plp-mount']).toBeDefined();
|
|
358
|
-
expect(
|
|
460
|
+
expect(result.orgConfig?.orgPageConfig?.mountingConfigs?.['plp-mount']).toBeDefined();
|
|
461
|
+
expect(
|
|
462
|
+
result.orgConfig?.orgPageConfig?.mountingConfigs?.['plp-mount']?.mountingConfigId,
|
|
463
|
+
).toBe('mc-1');
|
|
359
464
|
});
|
|
360
465
|
});
|
|
361
466
|
|
|
@@ -366,10 +471,16 @@ describe('fetchGraphQLConfig', () => {
|
|
|
366
471
|
colors: { values: { text_primary: '#111', background_primary: '#fff' } },
|
|
367
472
|
});
|
|
368
473
|
|
|
369
|
-
const result = await
|
|
474
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
475
|
+
'https://api.example.com',
|
|
476
|
+
'key',
|
|
477
|
+
'user_1',
|
|
478
|
+
[],
|
|
479
|
+
'app',
|
|
480
|
+
);
|
|
370
481
|
|
|
371
|
-
expect((result.colorsConfig as any)?.textPrimary).toBe('#111');
|
|
372
|
-
expect((result.colorsConfig as any)?.backgroundPrimary).toBe('#fff');
|
|
482
|
+
expect((result.orgConfig?.colorsConfig as any)?.textPrimary).toBe('#111');
|
|
483
|
+
expect((result.orgConfig?.colorsConfig as any)?.backgroundPrimary).toBe('#fff');
|
|
373
484
|
});
|
|
374
485
|
});
|
|
375
486
|
|
|
@@ -377,10 +488,16 @@ describe('fetchGraphQLConfig', () => {
|
|
|
377
488
|
it('returns config as-is when uiConfigs is absent', async () => {
|
|
378
489
|
makeOkFetch({ ...baseV3Config, ui_configs: undefined });
|
|
379
490
|
|
|
380
|
-
const result = await
|
|
491
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
492
|
+
'https://api.example.com',
|
|
493
|
+
'key',
|
|
494
|
+
'user_1',
|
|
495
|
+
[],
|
|
496
|
+
'app',
|
|
497
|
+
);
|
|
381
498
|
|
|
382
|
-
expect(result.frontendConfig).toBeDefined();
|
|
383
|
-
expect(result.colorsConfig).toBeDefined();
|
|
499
|
+
expect(result.orgConfig?.frontendConfig).toBeDefined();
|
|
500
|
+
expect(result.orgConfig?.colorsConfig).toBeDefined();
|
|
384
501
|
});
|
|
385
502
|
|
|
386
503
|
it('returns config as-is when floatingButton is absent', async () => {
|
|
@@ -391,9 +508,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
391
508
|
},
|
|
392
509
|
});
|
|
393
510
|
|
|
394
|
-
const result = await
|
|
511
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
512
|
+
'https://api.example.com',
|
|
513
|
+
'key',
|
|
514
|
+
'user_1',
|
|
515
|
+
[],
|
|
516
|
+
'app',
|
|
517
|
+
);
|
|
395
518
|
|
|
396
|
-
expect(result.frontendConfig).toBeDefined();
|
|
519
|
+
expect(result.orgConfig?.frontendConfig).toBeDefined();
|
|
397
520
|
});
|
|
398
521
|
|
|
399
522
|
it('returns config as-is when lookAndFeel is absent', async () => {
|
|
@@ -404,9 +527,15 @@ describe('fetchGraphQLConfig', () => {
|
|
|
404
527
|
},
|
|
405
528
|
});
|
|
406
529
|
|
|
407
|
-
const result = await
|
|
530
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
531
|
+
'https://api.example.com',
|
|
532
|
+
'key',
|
|
533
|
+
'user_1',
|
|
534
|
+
[],
|
|
535
|
+
'app',
|
|
536
|
+
);
|
|
408
537
|
|
|
409
|
-
expect(result.frontendConfig).toBeDefined();
|
|
538
|
+
expect(result.orgConfig?.frontendConfig).toBeDefined();
|
|
410
539
|
});
|
|
411
540
|
});
|
|
412
541
|
|
|
@@ -414,7 +543,7 @@ describe('fetchGraphQLConfig', () => {
|
|
|
414
543
|
it('sends a POST to the correct GraphQL endpoint with the API key', async () => {
|
|
415
544
|
makeOkFetch(null);
|
|
416
545
|
|
|
417
|
-
await
|
|
546
|
+
await fetchUnifiedGraphQLConfig('https://api.example.com', 'test-key', 'user_1', [], 'app');
|
|
418
547
|
|
|
419
548
|
expect(mockFetch).toHaveBeenCalledWith('https://api.example.com/v1/graphql', {
|
|
420
549
|
method: 'POST',
|
|
@@ -451,7 +580,7 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
451
580
|
it('issues a getWidgetConfig query (not getProductsConfigByVersion) and forwards userId', async () => {
|
|
452
581
|
makeUnifiedOkFetch(null);
|
|
453
582
|
|
|
454
|
-
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1');
|
|
583
|
+
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app');
|
|
455
584
|
|
|
456
585
|
const body = JSON.parse(mockFetch.mock.calls[0][1].body);
|
|
457
586
|
expect(body.query).toContain('getWidgetConfig');
|
|
@@ -459,7 +588,7 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
459
588
|
// userId is required by the schema; omitting it 400s. Regression guard.
|
|
460
589
|
// version is absent without a URL-param override so the resolver uses
|
|
461
590
|
// Statsig bucketing (passing 'deployed' here would bypass Statsig).
|
|
462
|
-
expect(body.variables).toEqual({ userId: 'user_1' });
|
|
591
|
+
expect(body.variables).toEqual({ userId: 'user_1', gateNames: [], source: 'app' });
|
|
463
592
|
});
|
|
464
593
|
|
|
465
594
|
it('threads a spiffy_config_version URL param through as the version variable', async () => {
|
|
@@ -467,10 +596,15 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
467
596
|
try {
|
|
468
597
|
makeUnifiedOkFetch(null);
|
|
469
598
|
|
|
470
|
-
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1');
|
|
599
|
+
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app');
|
|
471
600
|
|
|
472
601
|
const body = JSON.parse(mockFetch.mock.calls[0][1].body);
|
|
473
|
-
expect(body.variables).toEqual({
|
|
602
|
+
expect(body.variables).toEqual({
|
|
603
|
+
userId: 'user_1',
|
|
604
|
+
version: '1.2.3',
|
|
605
|
+
gateNames: [],
|
|
606
|
+
source: 'app',
|
|
607
|
+
});
|
|
474
608
|
} finally {
|
|
475
609
|
window.history.replaceState({}, '', '/');
|
|
476
610
|
}
|
|
@@ -479,11 +613,17 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
479
613
|
it('parses productsConfig into the same shape as fetchGraphQLConfig', async () => {
|
|
480
614
|
makeUnifiedOkFetch(baseV3Config);
|
|
481
615
|
|
|
482
|
-
const result = await fetchUnifiedGraphQLConfig(
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
616
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
617
|
+
'https://api.example.com',
|
|
618
|
+
'key',
|
|
619
|
+
'user_1',
|
|
620
|
+
[],
|
|
621
|
+
'app',
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
expect(result.orgConfig?.colorsConfig).toBeDefined();
|
|
625
|
+
expect(result.orgConfig?.frontendConfig).toBeDefined();
|
|
626
|
+
expect(result.orgConfig?.orgPageConfig).toBeDefined();
|
|
487
627
|
});
|
|
488
628
|
|
|
489
629
|
it('returns resolution metadata alongside the config so callers can thread baseVersion into inference', async () => {
|
|
@@ -492,9 +632,15 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
492
632
|
baseVersionSource: 'merchant_layer',
|
|
493
633
|
});
|
|
494
634
|
|
|
495
|
-
const result = await fetchUnifiedGraphQLConfig(
|
|
635
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
636
|
+
'https://api.example.com',
|
|
637
|
+
'key',
|
|
638
|
+
'user_1',
|
|
639
|
+
[],
|
|
640
|
+
'app',
|
|
641
|
+
);
|
|
496
642
|
|
|
497
|
-
expect(result.resolution).toEqual({
|
|
643
|
+
expect(result.orgConfig?.resolution).toEqual({
|
|
498
644
|
baseVersion: '1.0.670',
|
|
499
645
|
baseVersionSource: 'merchant_layer',
|
|
500
646
|
});
|
|
@@ -503,7 +649,7 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
503
649
|
it('selects resolution fields in the query so the server can fill them', async () => {
|
|
504
650
|
makeUnifiedOkFetch(null);
|
|
505
651
|
|
|
506
|
-
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1');
|
|
652
|
+
await fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app');
|
|
507
653
|
|
|
508
654
|
const body = JSON.parse(mockFetch.mock.calls[0][1].body);
|
|
509
655
|
expect(body.query).toContain('resolution');
|
|
@@ -516,16 +662,22 @@ describe('fetchUnifiedGraphQLConfig', () => {
|
|
|
516
662
|
// colors, DEFAULT_PAGE_VARIANTS is returned as the orgPageConfig.
|
|
517
663
|
makeUnifiedOkFetch(null);
|
|
518
664
|
|
|
519
|
-
const result = await fetchUnifiedGraphQLConfig(
|
|
665
|
+
const result = await fetchUnifiedGraphQLConfig(
|
|
666
|
+
'https://api.example.com',
|
|
667
|
+
'key',
|
|
668
|
+
'user_1',
|
|
669
|
+
[],
|
|
670
|
+
'app',
|
|
671
|
+
);
|
|
520
672
|
|
|
521
|
-
expect(result.orgPageConfig?.pageVariants).toEqual(DEFAULT_PAGE_VARIANTS);
|
|
673
|
+
expect(result.orgConfig?.orgPageConfig?.pageVariants).toEqual(DEFAULT_PAGE_VARIANTS);
|
|
522
674
|
});
|
|
523
675
|
|
|
524
|
-
it('
|
|
676
|
+
it('propagates the error on network failure', async () => {
|
|
525
677
|
mockFetch.mockRejectedValueOnce(new Error('boom'));
|
|
526
678
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
679
|
+
await expect(
|
|
680
|
+
fetchUnifiedGraphQLConfig('https://api.example.com', 'key', 'user_1', [], 'app'),
|
|
681
|
+
).rejects.toThrow('boom');
|
|
530
682
|
});
|
|
531
683
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { OrgConfigExperimentAssignment, OrgConfigFeatureGate } from 'src/application/models';
|
|
2
2
|
import { FeatureGates } from 'src/application/models/featureGates';
|
|
3
|
-
import { FeatureFlagService } from 'src/services/featureFlagService';
|
|
4
3
|
import type { GraphQlConfigValues } from 'src/contexts/graphqlContext';
|
|
5
4
|
import { configVersionOverride } from 'src/types/config-versions';
|
|
6
|
-
import {
|
|
5
|
+
import { fetchUnifiedGraphQLConfig } from './fetchGraphQLConfig';
|
|
7
6
|
|
|
8
7
|
// Short-lived so config changes (gates, experiments) still propagate within
|
|
9
8
|
// a session, while sparing every page navigation from re-fetching org
|
|
@@ -126,45 +125,20 @@ export class EnviveConfigService implements IEnviveConfigService {
|
|
|
126
125
|
return this.response;
|
|
127
126
|
}
|
|
128
127
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`${this.baseUrl}/v1/org/config?${queryParams.toString()}`,
|
|
144
|
-
{
|
|
145
|
-
method: 'GET',
|
|
146
|
-
headers: {
|
|
147
|
-
'Content-Type': 'application/json',
|
|
148
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
).then(async r => {
|
|
152
|
-
if (!r.ok) {
|
|
153
|
-
throw new Error(`Org config request failed with status ${r.status}`);
|
|
154
|
-
}
|
|
155
|
-
return r.json() as Promise<EnviveServiceConfig>;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// Honor URL / `window._spiffy` / localStorage overrides for
|
|
159
|
-
// `use_unified_config` the same way every other feature gate is read.
|
|
160
|
-
const useUnifiedConfig = new FeatureFlagService(
|
|
161
|
-
orgConfigResponse.gates ?? [],
|
|
162
|
-
).isFeatureGateEnabled(FeatureGates.UseUnifiedConfig);
|
|
163
|
-
const orgConfig = useUnifiedConfig
|
|
164
|
-
? await fetchUnifiedGraphQLConfig(this.baseUrl, this.apiKey, this.userId)
|
|
165
|
-
: await fetchGraphQLConfig(this.baseUrl, this.apiKey);
|
|
166
|
-
|
|
167
|
-
this.response = { ...orgConfigResponse, orgConfig };
|
|
128
|
+
// getWidgetConfig is the single source of session config: it returns org
|
|
129
|
+
// identity + feature gates + experiment assignments (which used to be a
|
|
130
|
+
// separate GET /v1/org/config call) alongside productsConfig + the
|
|
131
|
+
// resolution metadata threaded into downstream inference. `gateNames` is the
|
|
132
|
+
// list of gates the app checks, so the resolver evaluates and returns them.
|
|
133
|
+
const gateNames = Object.values(FeatureGates).map(featureGate => featureGate.toString());
|
|
134
|
+
|
|
135
|
+
this.response = await fetchUnifiedGraphQLConfig(
|
|
136
|
+
this.baseUrl,
|
|
137
|
+
this.apiKey,
|
|
138
|
+
this.userId,
|
|
139
|
+
gateNames,
|
|
140
|
+
this.source,
|
|
141
|
+
);
|
|
168
142
|
this.writeCachedConfig(this.response);
|
|
169
143
|
return this.response;
|
|
170
144
|
}
|