@komaci/prefetch 242.2.4 → 244.0.0

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prefetchService.spec.d.ts.map
@@ -0,0 +1,865 @@
1
+ import waitForExpect from 'wait-for-expect';
2
+ import { getPrefetchService } from '../modules/komaci/prefetch/prefetch';
3
+ import { setupRouterMock, createPageRef, setupPrefetch, defaultRoutingResult, mockPrefetchConfig, mockPrefetchConfigStatusError, mockPrefetchConfigStateError, createAdgModule, } from './utils';
4
+ jest.mock('lwr/router');
5
+ import * as ResolverApi from 'komaci/resolver';
6
+ import { getInstrumentation } from 'o11y/client';
7
+ const mockInstrumentation = getInstrumentation('komaci');
8
+ beforeEach(() => {
9
+ jest.clearAllMocks();
10
+ });
11
+ afterEach(() => {
12
+ expect.hasAssertions();
13
+ });
14
+ jest.setTimeout(500);
15
+ function invokeCallbackWithState(
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ callback, state, errors = [], index = 0) {
18
+ callback === null || callback === void 0 ? void 0 : callback({
19
+ index,
20
+ status: {
21
+ getState: function () {
22
+ return state;
23
+ },
24
+ getErrorMessages: function () {
25
+ return errors;
26
+ },
27
+ },
28
+ });
29
+ }
30
+ describe('prefetchService', () => {
31
+ describe('calling prefetch', () => {
32
+ it('throws if no router is given', () => {
33
+ expect(() => {
34
+ getPrefetchService(null, []);
35
+ }).toThrowError(/Must provide Router./);
36
+ });
37
+ it('constructs when given valid router', () => {
38
+ const { createRouter } = setupRouterMock();
39
+ const router = createRouter({});
40
+ const prefetchService = getPrefetchService(router, []);
41
+ expect(prefetchService).toBeDefined();
42
+ });
43
+ });
44
+ describe('prefetching an address', () => {
45
+ const pageRef = createPageRef();
46
+ it('calls onUpdateState with "running" upon init', async () => {
47
+ expect.assertions(3);
48
+ const { createRouter } = setupRouterMock();
49
+ const onStateChanged = mockPrefetchConfig.onStateChanged;
50
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
51
+ const service = setup.run();
52
+ await waitForExpect(() => {
53
+ expect(onStateChanged).toHaveBeenCalledTimes(2);
54
+ expect(onStateChanged).toHaveBeenCalledWith(expect.objectContaining({ state: 'running' }));
55
+ expect(service.getState()).toBe('done');
56
+ });
57
+ });
58
+ it('calls bulkResolver with adgInput', async () => {
59
+ expect.assertions(3);
60
+ const routingResult = defaultRoutingResult(pageRef);
61
+ const { viewset = {} } = routingResult;
62
+ let adgModulesImporter;
63
+ if (viewset['default']) {
64
+ const viewInfo = viewset['default'];
65
+ const komaciSpecifier = '@salesforce/komaci/' + viewInfo.specifier.replace('/', '__');
66
+ adgModulesImporter = () => import(komaciSpecifier);
67
+ }
68
+ const adgFn = (await (adgModulesImporter === null || adgModulesImporter === void 0 ? void 0 : adgModulesImporter())).default;
69
+ const { createRouter } = setupRouterMock(() => routingResult);
70
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
71
+ setup.run();
72
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
73
+ await waitForExpect(() => {
74
+ expect(mockGetBulkAdgResolver).toBeCalledTimes(1);
75
+ expect(mockGetBulkAdgResolver).toBeCalledWith(adgFn, expect.arrayContaining([
76
+ expect.objectContaining({
77
+ context: { CurrentPageReference: pageRef },
78
+ }),
79
+ ]), expect.anything(), {
80
+ downloadImageFunc: undefined,
81
+ instrumentationCtx: {
82
+ isRootActivitySampled: true,
83
+ rootId: 'abcd-1234',
84
+ },
85
+ MaxResolutionDepth: 512,
86
+ WireTimeout: 180 * 1000,
87
+ WireSlowRunningTimeout: 30 * 1000,
88
+ });
89
+ expect(mockGetBulkAdgResolver.mock.calls[0][1]).toHaveLength(1);
90
+ });
91
+ });
92
+ it('calls onAddressProcessed & onStateChanged', async () => {
93
+ expect.assertions(7);
94
+ const { createRouter } = setupRouterMock();
95
+ const { onAddressProcessed, onStateChanged } = mockPrefetchConfig;
96
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
97
+ const prefetchService = setup.run();
98
+ await waitForExpect(() => {
99
+ expect(onStateChanged).toBeCalledTimes(2);
100
+ expect(onStateChanged).toHaveBeenNthCalledWith(1, expect.objectContaining({ state: 'running' }));
101
+ expect(onAddressProcessed).toBeCalledTimes(1);
102
+ expect(onAddressProcessed).toHaveBeenCalledWith(expect.objectContaining({
103
+ state: 'completed',
104
+ address: pageRef,
105
+ }));
106
+ expect(onStateChanged).toHaveBeenNthCalledWith(2, expect.objectContaining({ state: 'done' }));
107
+ onStateChanged.mockClear();
108
+ prefetchService.stop();
109
+ expect(onStateChanged).toBeCalledTimes(1);
110
+ expect(onStateChanged).toBeCalledWith(expect.objectContaining({ state: 'stopped' }));
111
+ });
112
+ });
113
+ it('prefetchService.stop() updates onStateChanged to "stopped"', async () => {
114
+ expect.assertions(5);
115
+ const onStateChanged = mockPrefetchConfig.onStateChanged;
116
+ const { createRouter } = setupRouterMock();
117
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
118
+ const service = setup.run();
119
+ await waitForExpect(() => {
120
+ expect(onStateChanged).toHaveBeenCalledTimes(2);
121
+ expect(onStateChanged).toHaveBeenNthCalledWith(1, expect.objectContaining({ state: 'running' }));
122
+ expect(onStateChanged).toHaveBeenNthCalledWith(2, expect.objectContaining({ state: 'done' }));
123
+ service.stop();
124
+ expect(onStateChanged).toHaveBeenNthCalledWith(3, expect.objectContaining({ state: 'stopped' }));
125
+ onStateChanged.mockClear();
126
+ service.stop();
127
+ expect(onStateChanged).toHaveBeenCalledTimes(0);
128
+ });
129
+ });
130
+ it('calls onStateChanged with "stopped", even if a batch has no resolvers', async () => {
131
+ expect.assertions(4);
132
+ const onStateChanged = mockPrefetchConfig.onStateChanged;
133
+ const { createRouter } = setupRouterMock();
134
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
135
+ const service = setup.run();
136
+ service.adgMap.set(() => ({}), {
137
+ addresses: [],
138
+ resolverInputStatus: [],
139
+ });
140
+ service.stop();
141
+ await waitForExpect(() => {
142
+ expect(onStateChanged).toHaveBeenCalledTimes(2);
143
+ expect(onStateChanged).toHaveBeenNthCalledWith(1, expect.objectContaining({ state: 'running' }));
144
+ expect(onStateChanged).toHaveBeenNthCalledWith(2, expect.objectContaining({ state: 'stopped' }));
145
+ onStateChanged.mockClear();
146
+ service.stop();
147
+ expect(onStateChanged).toHaveBeenCalledTimes(0);
148
+ });
149
+ });
150
+ it('call instrumentation counter correctly', async () => {
151
+ expect.assertions(1);
152
+ const { createRouter } = setupRouterMock();
153
+ setupPrefetch(createRouter, [pageRef], mockPrefetchConfig).run();
154
+ await waitForExpect(() => {
155
+ expect(mockInstrumentation.incrementCounter).toBeCalledWith('prefetch.route-success', 1);
156
+ });
157
+ });
158
+ });
159
+ describe('unexpected scenarios', () => {
160
+ const { createRouter } = setupRouterMock();
161
+ const pageRef = createPageRef();
162
+ it('gracefully handles router result with no viewset', async () => {
163
+ expect.assertions(5);
164
+ const { onStateChanged, onAddressProcessed } = mockPrefetchConfig;
165
+ createRouter.mockImplementationOnce(() => {
166
+ return {
167
+ resolveView: jest
168
+ .fn()
169
+ .mockImplementation(() => {
170
+ return Promise.resolve({ viewset: {} });
171
+ }),
172
+ };
173
+ });
174
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
175
+ setup.run();
176
+ await waitForExpect(() => {
177
+ expect(onStateChanged).toBeCalledTimes(2);
178
+ expect(onStateChanged).toHaveBeenNthCalledWith(1, expect.objectContaining({ state: 'running' }));
179
+ expect(onStateChanged).toHaveBeenNthCalledWith(2, expect.objectContaining({ state: 'done' }));
180
+ expect(onAddressProcessed).toBeCalledTimes(1);
181
+ expect(onAddressProcessed).toHaveBeenCalledWith(expect.objectContaining({
182
+ state: 'rejected',
183
+ reasons: [
184
+ expect.stringContaining('No ADG module found for given address'),
185
+ ],
186
+ }));
187
+ });
188
+ });
189
+ it('calls onStateChanged with "error" when bulk resolver error state with invalid index', async () => {
190
+ expect.assertions(2);
191
+ const { onStateChanged } = mockPrefetchConfig;
192
+ jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, _inputs, callbacks) => {
193
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running');
194
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done', ['nothing good'], 1);
195
+ return { start: jest.fn(), stop: jest.fn() };
196
+ });
197
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
198
+ setup.run();
199
+ await waitForExpect(() => {
200
+ expect(onStateChanged).toBeCalledTimes(2);
201
+ expect(onStateChanged).toHaveBeenLastCalledWith(expect.objectContaining({
202
+ state: 'error',
203
+ message: expect.stringContaining('Invalid index provided by resolver'),
204
+ }));
205
+ });
206
+ });
207
+ it('handles onAddressProcessed that throws error', async () => {
208
+ expect.assertions(2);
209
+ const { createRouter } = setupRouterMock();
210
+ const onAddressProcessed = mockPrefetchConfigStatusError.onAddressProcessed;
211
+ const onStateChanged = mockPrefetchConfigStatusError.onStateChanged;
212
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfigStatusError);
213
+ setup.run();
214
+ await waitForExpect(() => {
215
+ expect(onAddressProcessed).toThrowError();
216
+ expect(onStateChanged).toBeCalled();
217
+ });
218
+ });
219
+ it('handles onStateChanged that throws error', async () => {
220
+ expect.assertions(1);
221
+ const { createRouter } = setupRouterMock();
222
+ const onStateChanged = mockPrefetchConfigStateError.onStateChanged;
223
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfigStateError);
224
+ setup.run();
225
+ await waitForExpect(() => {
226
+ expect(onStateChanged).toThrowError();
227
+ });
228
+ });
229
+ it('calls onStateChanged with "error" when bulk resolver emits an invalid status', async () => {
230
+ expect.assertions(3);
231
+ const { onStateChanged } = mockPrefetchConfig;
232
+ jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, _inputs, callbacks) => {
233
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running');
234
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'arfdarf');
235
+ return { start: jest.fn(), stop: jest.fn() };
236
+ });
237
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
238
+ const service = setup.run();
239
+ await waitForExpect(() => {
240
+ expect(onStateChanged).toBeCalledTimes(2);
241
+ expect(onStateChanged).toHaveBeenLastCalledWith(expect.objectContaining({
242
+ state: 'error',
243
+ message: expect.stringContaining('Unexpected resolution status'),
244
+ }));
245
+ expect(service.resolutionGroups[0].bulkResolver).not.toBe(undefined);
246
+ });
247
+ });
248
+ it('should gracefully handle a module importer that throws an exception', async () => {
249
+ expect.assertions(7);
250
+ const pageRef1 = createPageRef('action1');
251
+ const pageRef2 = createPageRef('action2');
252
+ const pageRef3 = createPageRef('action3');
253
+ const pageRef2Reason = 'Module importer error';
254
+ const pageRef1Importer = () => Promise.resolve(createAdgModule());
255
+ const pageRef2Importer = () => Promise.reject(new Error(pageRef2Reason));
256
+ const pageRef3Importer = () => Promise.reject();
257
+ const { onAddressProcessed, onStateChanged } = mockPrefetchConfig;
258
+ const { createRouter } = setupRouterMock((address) => {
259
+ const result = defaultRoutingResult(address);
260
+ const importer = address == pageRef1
261
+ ? pageRef1Importer
262
+ : (address == pageRef2 && pageRef2Importer) ||
263
+ pageRef3Importer;
264
+ return {
265
+ ...result,
266
+ viewset: {
267
+ komaci: importer,
268
+ },
269
+ };
270
+ });
271
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2, pageRef3], mockPrefetchConfig);
272
+ setup.run();
273
+ await waitForExpect(() => {
274
+ expect(onStateChanged).toBeCalledTimes(2);
275
+ expect(onStateChanged).toHaveBeenNthCalledWith(1, expect.objectContaining({ state: 'running' }));
276
+ expect(onStateChanged).toHaveBeenNthCalledWith(2, expect.objectContaining({ state: 'done' }));
277
+ expect(onAddressProcessed).toBeCalledTimes(3);
278
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(1, expect.objectContaining({
279
+ state: 'rejected',
280
+ address: pageRef2,
281
+ reasons: expect.arrayContaining([
282
+ 'Unexpected exception processing routing result: ' +
283
+ pageRef2Reason,
284
+ ]),
285
+ }));
286
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(2, expect.objectContaining({
287
+ state: 'rejected',
288
+ address: pageRef3,
289
+ reasons: expect.arrayContaining([
290
+ expect.stringContaining('Unknown exception processing routing result.'),
291
+ ]),
292
+ }));
293
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(3, expect.objectContaining({
294
+ state: 'completed',
295
+ address: pageRef1,
296
+ }));
297
+ });
298
+ });
299
+ describe('invalid routers or invalid routes', () => {
300
+ const pageRefs = [createPageRef('action1'), createPageRef('action2')];
301
+ it('should call onAddressProcessed with rejected if router is invalid', async () => {
302
+ expect.assertions(6);
303
+ const { createRouter } = setupRouterMock();
304
+ const router = createRouter();
305
+ router.resolveView.mockImplementation(() => {
306
+ throw new Error('Invalid route.');
307
+ });
308
+ const { onStateChanged, onAddressProcessed } = mockPrefetchConfig;
309
+ getPrefetchService(router, pageRefs, mockPrefetchConfig);
310
+ await waitForExpect(() => {
311
+ expect(onAddressProcessed).toBeCalledTimes(2);
312
+ expect(onAddressProcessed.mock.calls[0][0]).toEqual({
313
+ address: pageRefs[0],
314
+ state: 'rejected',
315
+ reasons: ['Unexpected exception during routing: Invalid route.'],
316
+ });
317
+ expect(onAddressProcessed.mock.calls[1][0]).toEqual({
318
+ address: pageRefs[1],
319
+ state: 'rejected',
320
+ reasons: ['Unexpected exception during routing: Invalid route.'],
321
+ });
322
+ expect(onStateChanged).toBeCalledTimes(2);
323
+ expect(onStateChanged.mock.calls[0][0]).toEqual({
324
+ state: 'running',
325
+ abandoned: [],
326
+ });
327
+ expect(onStateChanged.mock.calls[1][0]).toEqual({
328
+ state: 'done',
329
+ abandoned: [],
330
+ message: 'no processable addresses, do not bulkResolve and set state to "done"',
331
+ });
332
+ });
333
+ });
334
+ it('should call onAddressProcessed with rejected if one route is invalid', async () => {
335
+ expect.assertions(6);
336
+ const { createRouter } = setupRouterMock();
337
+ const router = createRouter();
338
+ router.resolveView.mockImplementationOnce(() => {
339
+ throw new Error('Invalid route.');
340
+ });
341
+ const { onStateChanged, onAddressProcessed } = mockPrefetchConfig;
342
+ getPrefetchService(router, pageRefs, mockPrefetchConfig);
343
+ await waitForExpect(() => {
344
+ expect(onAddressProcessed).toBeCalledTimes(2);
345
+ expect(onAddressProcessed.mock.calls[0][0]).toEqual({
346
+ address: pageRefs[0],
347
+ state: 'rejected',
348
+ reasons: ['Unexpected exception during routing: Invalid route.'],
349
+ });
350
+ expect(onAddressProcessed.mock.calls[1][0]).toEqual({
351
+ address: pageRefs[1],
352
+ state: 'completed',
353
+ reasons: [],
354
+ });
355
+ expect(onStateChanged).toBeCalledTimes(2);
356
+ expect(onStateChanged.mock.calls[0][0]).toEqual({
357
+ state: 'running',
358
+ abandoned: [],
359
+ });
360
+ expect(onStateChanged.mock.calls[1][0]).toEqual({
361
+ state: 'done',
362
+ abandoned: [],
363
+ message: '',
364
+ });
365
+ });
366
+ });
367
+ });
368
+ });
369
+ describe('prefetch two addresses and call bulkResolver', () => {
370
+ const pageRef1 = createPageRef('action1');
371
+ const pageRef2 = createPageRef('action1', '2');
372
+ const adgModule = createAdgModule();
373
+ const adgFunction = adgModule.default;
374
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
375
+ const adgModuleImporter = () => Promise.resolve(adgModule);
376
+ const init = () => setupRouterMock((address) => {
377
+ const result = defaultRoutingResult(address);
378
+ return {
379
+ ...result,
380
+ viewset: {
381
+ komaci: adgModuleImporter,
382
+ },
383
+ };
384
+ });
385
+ describe('pageRef1 && pageRef2 => adgModule1', () => {
386
+ it('calls bulkResolver once with two adgInputs', async () => {
387
+ expect.assertions(3);
388
+ const { createRouter } = init();
389
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
390
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2], mockPrefetchConfig);
391
+ setup.run();
392
+ await waitForExpect(() => {
393
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledTimes(1);
394
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledWith(adgFunction, expect.arrayContaining([
395
+ expect.objectContaining({
396
+ context: { CurrentPageReference: pageRef1 },
397
+ }),
398
+ expect.objectContaining({
399
+ context: { CurrentPageReference: pageRef2 },
400
+ }),
401
+ ]), expect.anything(), {
402
+ downloadImageFunc: undefined,
403
+ instrumentationCtx: {
404
+ isRootActivitySampled: true,
405
+ rootId: 'abcd-1234',
406
+ },
407
+ MaxResolutionDepth: 512,
408
+ WireTimeout: 180 * 1000,
409
+ WireSlowRunningTimeout: 30 * 1000,
410
+ });
411
+ expect(mockGetBulkAdgResolver.mock.calls[0][1]).toHaveLength(2);
412
+ });
413
+ });
414
+ });
415
+ describe('pageRef1 & pageRef2 => adgModule1, pageRef2 => raises resolver error', () => {
416
+ const pageRef1 = createPageRef('action1');
417
+ const pageRef2 = createPageRef('action2');
418
+ const adgModule1 = createAdgModule();
419
+ const adgFunction1 = adgModule1.default;
420
+ const adgModuleImporter1 = () => Promise.resolve(adgModule1);
421
+ const { onAddressProcessed } = mockPrefetchConfig;
422
+ it('calls onAddressProcessed twice: pageRef1 => completed, pageRef2 => rejected', async () => {
423
+ expect.assertions(5);
424
+ const { createRouter } = setupRouterMock((address) => {
425
+ const result = defaultRoutingResult(address);
426
+ return {
427
+ ...result,
428
+ viewset: {
429
+ komaci: adgModuleImporter1,
430
+ },
431
+ };
432
+ });
433
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, inputs, callbacks) => {
434
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done', [
435
+ 'Error processing input',
436
+ JSON.stringify(inputs[1], null, 4),
437
+ ], 1);
438
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done');
439
+ return { start: jest.fn(), stop: jest.fn() };
440
+ });
441
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2], mockPrefetchConfig);
442
+ setup.run();
443
+ await waitForExpect(() => {
444
+ expect(mockGetBulkAdgResolver).toBeCalledTimes(1);
445
+ expect(mockGetBulkAdgResolver).toHaveBeenNthCalledWith(1, adgFunction1, expect.arrayContaining([
446
+ expect.objectContaining({
447
+ context: { CurrentPageReference: pageRef1 },
448
+ }),
449
+ ]), expect.anything(), {
450
+ downloadImageFunc: undefined,
451
+ instrumentationCtx: {
452
+ isRootActivitySampled: true,
453
+ rootId: 'abcd-1234',
454
+ },
455
+ MaxResolutionDepth: 512,
456
+ WireTimeout: 180 * 1000,
457
+ WireSlowRunningTimeout: 30 * 1000,
458
+ });
459
+ expect(onAddressProcessed).toHaveBeenCalledTimes(2);
460
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(1, expect.objectContaining({
461
+ state: 'rejected',
462
+ address: pageRef2,
463
+ }));
464
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(2, expect.objectContaining({
465
+ state: 'completed',
466
+ address: pageRef1,
467
+ }));
468
+ });
469
+ });
470
+ });
471
+ describe('pageRef1 => adgModule1, pageRef2 => adgModule2', () => {
472
+ const pageRef1 = createPageRef('action1');
473
+ const pageRef2 = createPageRef('action2');
474
+ const adgModule1 = createAdgModule();
475
+ const adgModule2 = createAdgModule();
476
+ const adgFunction1 = adgModule1.default;
477
+ const adgFunction2 = adgModule2.default;
478
+ const adgModuleImporter1 = () => Promise.resolve(adgModule1);
479
+ const adgModuleImporter2 = () => Promise.resolve(adgModule2);
480
+ const init = () => setupRouterMock((address) => {
481
+ const result = defaultRoutingResult(address);
482
+ return {
483
+ ...result,
484
+ viewset: {
485
+ komaci: address.attributes.apiName == 'action1'
486
+ ? adgModuleImporter1
487
+ : adgModuleImporter2,
488
+ },
489
+ };
490
+ });
491
+ it('calls bulkResolver twice with one adgInput each time', async () => {
492
+ expect.assertions(3);
493
+ const { createRouter } = init();
494
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
495
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2], mockPrefetchConfig);
496
+ setup.run();
497
+ await waitForExpect(() => {
498
+ expect(mockGetBulkAdgResolver).toBeCalledTimes(2);
499
+ expect(mockGetBulkAdgResolver).toHaveBeenNthCalledWith(1, adgFunction1, expect.arrayContaining([
500
+ expect.objectContaining({
501
+ context: { CurrentPageReference: pageRef1 },
502
+ }),
503
+ ]), expect.anything(), {
504
+ downloadImageFunc: undefined,
505
+ instrumentationCtx: {
506
+ isRootActivitySampled: true,
507
+ rootId: 'abcd-1234',
508
+ },
509
+ MaxResolutionDepth: 512,
510
+ WireTimeout: 180 * 1000,
511
+ WireSlowRunningTimeout: 30 * 1000,
512
+ });
513
+ expect(mockGetBulkAdgResolver).toHaveBeenNthCalledWith(2, adgFunction2, expect.arrayContaining([
514
+ expect.objectContaining({
515
+ context: { CurrentPageReference: pageRef2 },
516
+ }),
517
+ ]), expect.anything(), {
518
+ downloadImageFunc: undefined,
519
+ instrumentationCtx: {
520
+ isRootActivitySampled: true,
521
+ rootId: 'abcd-1234',
522
+ },
523
+ MaxResolutionDepth: 512,
524
+ WireTimeout: 180 * 1000,
525
+ WireSlowRunningTimeout: 30 * 1000,
526
+ });
527
+ });
528
+ });
529
+ const { onStateChanged, onAddressProcessed } = mockPrefetchConfig;
530
+ it('prefetch state waits to emit done until all resolvers are done', async () => {
531
+ expect.assertions(7);
532
+ const { createRouter } = init();
533
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
534
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2], mockPrefetchConfig);
535
+ setup.run();
536
+ await waitForExpect(() => {
537
+ expect(mockGetBulkAdgResolver).toBeCalledTimes(2);
538
+ expect(onStateChanged).toBeCalledTimes(2);
539
+ expect(onStateChanged).toBeCalledWith(expect.objectContaining({
540
+ state: 'running',
541
+ }));
542
+ expect(onAddressProcessed).toBeCalledTimes(2);
543
+ expect(onAddressProcessed).toHaveBeenCalledWith(expect.objectContaining({
544
+ state: 'completed',
545
+ address: pageRef1,
546
+ }));
547
+ expect(onAddressProcessed).toHaveBeenCalledWith(expect.objectContaining({
548
+ state: 'completed',
549
+ address: pageRef2,
550
+ }));
551
+ expect(onStateChanged).toHaveBeenLastCalledWith(expect.objectContaining({
552
+ state: 'done',
553
+ }));
554
+ });
555
+ });
556
+ });
557
+ describe('pageRef1 => adgModule1, pageRef2 => null', () => {
558
+ const pageRef1 = createPageRef('action1');
559
+ const pageRef2 = createPageRef('action2');
560
+ const adgModule1 = createAdgModule();
561
+ const adgFunction1 = adgModule1.default;
562
+ const adgModuleImporter1 = () => Promise.resolve(adgModule1);
563
+ const { onAddressProcessed, onStateChanged } = mockPrefetchConfig;
564
+ it('calls onAddressedProcessed twice: pageRef1 => completed, pageRef2 => rejected', async () => {
565
+ const { createRouter } = setupRouterMock((address) => {
566
+ const result = defaultRoutingResult(address);
567
+ const viewset = address.attributes.apiName == 'action1'
568
+ ? {
569
+ komaci: adgModuleImporter1,
570
+ }
571
+ : {};
572
+ return {
573
+ ...result,
574
+ viewset,
575
+ };
576
+ });
577
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
578
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef2], mockPrefetchConfig);
579
+ expect.assertions(6);
580
+ setup.run();
581
+ await waitForExpect(() => {
582
+ expect(mockGetBulkAdgResolver).toBeCalledTimes(1);
583
+ expect(mockGetBulkAdgResolver).toHaveBeenNthCalledWith(1, adgFunction1, expect.arrayContaining([
584
+ expect.objectContaining({
585
+ context: { CurrentPageReference: pageRef1 },
586
+ }),
587
+ ]), expect.anything(), {
588
+ downloadImageFunc: undefined,
589
+ instrumentationCtx: {
590
+ isRootActivitySampled: true,
591
+ rootId: 'abcd-1234',
592
+ },
593
+ MaxResolutionDepth: 512,
594
+ WireTimeout: 180 * 1000,
595
+ WireSlowRunningTimeout: 30 * 1000,
596
+ });
597
+ expect(onStateChanged).toHaveBeenCalledTimes(2);
598
+ expect(onAddressProcessed).toHaveBeenCalledTimes(2);
599
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(1, expect.objectContaining({
600
+ state: 'rejected',
601
+ address: pageRef2,
602
+ }));
603
+ expect(onAddressProcessed).toHaveBeenNthCalledWith(2, expect.objectContaining({
604
+ state: 'completed',
605
+ address: pageRef1,
606
+ }));
607
+ });
608
+ });
609
+ });
610
+ });
611
+ describe('PrefetchConfig Option Tests', () => {
612
+ describe('maxConcurrent Tests', () => {
613
+ describe('prefetch two addresses and call bulkResolver with maxConcurrent', () => {
614
+ const pageRef1_1 = createPageRef('action1');
615
+ const pageRef1_2 = createPageRef('action1', '2');
616
+ const pageRef2_1 = createPageRef('action2');
617
+ const pageRef2_2 = createPageRef('action2', '2');
618
+ const adgModule1 = createAdgModule();
619
+ const adgModule2 = createAdgModule();
620
+ const adgFunction1 = adgModule1.default;
621
+ const adgFunction2 = adgModule2.default;
622
+ const adgModuleImporter1 = () => Promise.resolve(adgModule1);
623
+ const adgModuleImporter2 = () => Promise.resolve(adgModule2);
624
+ const init = () => setupRouterMock((address) => {
625
+ const result = defaultRoutingResult(address);
626
+ return {
627
+ ...result,
628
+ viewset: {
629
+ komaci: address.attributes.apiName == 'action1'
630
+ ? adgModuleImporter1
631
+ : adgModuleImporter2,
632
+ },
633
+ };
634
+ });
635
+ describe('pageRef1 && pageRef2 => adgModule1, but maxConcurrent: 1', () => {
636
+ it('calls bulkResolver twice with two adgInputs', async () => {
637
+ const prefetchConfigWithConcurrent = {
638
+ ...mockPrefetchConfig,
639
+ maxConcurrent: 1,
640
+ };
641
+ expect.assertions(5);
642
+ const { createRouter } = init();
643
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
644
+ const setup = setupPrefetch(createRouter, [pageRef1_1, pageRef1_2], prefetchConfigWithConcurrent);
645
+ setup.run();
646
+ await waitForExpect(() => {
647
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledTimes(2);
648
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledWith(adgFunction1, expect.arrayContaining([
649
+ expect.objectContaining({
650
+ context: { CurrentPageReference: pageRef1_1 },
651
+ }),
652
+ ]), expect.anything(), {
653
+ downloadImageFunc: undefined,
654
+ instrumentationCtx: {
655
+ isRootActivitySampled: true,
656
+ rootId: 'abcd-1234',
657
+ },
658
+ MaxResolutionDepth: 512,
659
+ WireTimeout: 180 * 1000,
660
+ WireSlowRunningTimeout: 30 * 1000,
661
+ });
662
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledWith(adgFunction1, expect.arrayContaining([
663
+ expect.objectContaining({
664
+ context: { CurrentPageReference: pageRef1_2 },
665
+ }),
666
+ ]), expect.anything(), {
667
+ downloadImageFunc: undefined,
668
+ instrumentationCtx: {
669
+ isRootActivitySampled: true,
670
+ rootId: 'abcd-1234',
671
+ },
672
+ MaxResolutionDepth: 512,
673
+ WireTimeout: 180 * 1000,
674
+ WireSlowRunningTimeout: 30 * 1000,
675
+ });
676
+ expect(mockGetBulkAdgResolver.mock.calls[0][1]).toHaveLength(1);
677
+ expect(mockGetBulkAdgResolver.mock.calls[1][1]).toHaveLength(1);
678
+ });
679
+ });
680
+ });
681
+ describe('pageRef1 && pageRef2 => adgModule1 and pageRef3 && pageRef4 => adgModule2, but maxConcurrent: 3', () => {
682
+ it('calls bulkResolver twice with two adgInputs', async () => {
683
+ const prefetchConfigWithConcurrent = {
684
+ ...mockPrefetchConfig,
685
+ maxConcurrent: 3,
686
+ };
687
+ expect.assertions(6);
688
+ const { createRouter } = init();
689
+ const mockGetBulkAdgResolver = jest.spyOn(ResolverApi, 'getBulkAdgResolver');
690
+ const setup = setupPrefetch(createRouter, [pageRef1_1, pageRef2_1, pageRef1_2, pageRef2_2], prefetchConfigWithConcurrent);
691
+ const prefetchService = setup.run();
692
+ await waitForExpect(() => {
693
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledTimes(2);
694
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledWith(adgFunction1, expect.arrayContaining([
695
+ expect.objectContaining({
696
+ context: { CurrentPageReference: pageRef1_1 },
697
+ }),
698
+ expect.objectContaining({
699
+ context: { CurrentPageReference: pageRef1_2 },
700
+ }),
701
+ ]), expect.anything(), {
702
+ downloadImageFunc: undefined,
703
+ instrumentationCtx: {
704
+ isRootActivitySampled: true,
705
+ rootId: 'abcd-1234',
706
+ },
707
+ MaxResolutionDepth: 512,
708
+ WireTimeout: 180 * 1000,
709
+ WireSlowRunningTimeout: 30 * 1000,
710
+ });
711
+ expect(mockGetBulkAdgResolver).toHaveBeenCalledWith(adgFunction2, expect.arrayContaining([
712
+ expect.objectContaining({
713
+ context: { CurrentPageReference: pageRef2_1 },
714
+ }),
715
+ expect.objectContaining({
716
+ context: { CurrentPageReference: pageRef2_2 },
717
+ }),
718
+ ]), expect.anything(), {
719
+ downloadImageFunc: undefined,
720
+ instrumentationCtx: {
721
+ isRootActivitySampled: true,
722
+ rootId: 'abcd-1234',
723
+ },
724
+ MaxResolutionDepth: 512,
725
+ WireTimeout: 180 * 1000,
726
+ WireSlowRunningTimeout: 30 * 1000,
727
+ });
728
+ expect(mockGetBulkAdgResolver.mock.calls[0][1]).toHaveLength(2);
729
+ expect(mockGetBulkAdgResolver.mock.calls[1][1]).toHaveLength(2);
730
+ expect(prefetchService.resolutionGroups[1].bulkResolver).toBe(undefined);
731
+ });
732
+ });
733
+ });
734
+ });
735
+ });
736
+ describe('highVolumePriming Tests', () => {
737
+ it('Only assigns 1 address to each AdgModule for resolution', async () => {
738
+ const pageRef1 = createPageRef('action1');
739
+ const adgModule1 = createAdgModule();
740
+ const adgFunction1 = adgModule1.default;
741
+ let addressesPrimedResolve;
742
+ let addressCount = 0;
743
+ const addressesPrimedPromise = new Promise((resolve) => {
744
+ addressesPrimedResolve = resolve;
745
+ });
746
+ const adgModuleImporter1 = () => {
747
+ addressCount++;
748
+ if (addressCount >= 2) {
749
+ addressesPrimedResolve();
750
+ }
751
+ return Promise.resolve(adgModule1);
752
+ };
753
+ const { createRouter } = setupRouterMock((address) => {
754
+ const result = defaultRoutingResult(address);
755
+ return {
756
+ ...result,
757
+ viewset: {
758
+ komaci: adgModuleImporter1,
759
+ },
760
+ };
761
+ });
762
+ const prefetchConfigWithHighVolumePriming = {
763
+ highVolumePriming: true,
764
+ };
765
+ const setup = setupPrefetch(createRouter, [pageRef1, pageRef1], prefetchConfigWithHighVolumePriming);
766
+ const prefetchService = setup.run();
767
+ await addressesPrimedPromise;
768
+ expect(prefetchService['adgMap'].size).toEqual(1);
769
+ expect(prefetchService['adgMap'].get(adgFunction1)).toHaveLength(1);
770
+ });
771
+ });
772
+ });
773
+ describe('onStateChanged should be called with errorMessage', () => {
774
+ const { createRouter } = setupRouterMock();
775
+ const pageRef = createPageRef();
776
+ it('calls onStateChanged with error message', async () => {
777
+ expect.assertions(3);
778
+ const { onStateChanged } = mockPrefetchConfig;
779
+ const ERROR = 'I am error';
780
+ jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, inputs, callbacks) => {
781
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running');
782
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done', [
783
+ ERROR,
784
+ ]);
785
+ return { start: jest.fn(), stop: jest.fn() };
786
+ });
787
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
788
+ const service = setup.run();
789
+ await waitForExpect(() => {
790
+ expect(onStateChanged).toBeCalledTimes(2);
791
+ expect(onStateChanged).toHaveBeenLastCalledWith(expect.objectContaining({
792
+ state: 'done',
793
+ message: expect.stringContaining(ERROR),
794
+ }));
795
+ expect(service.resolutionGroups[0].bulkResolver).not.toBe(undefined);
796
+ onStateChanged.mockClear();
797
+ service.stop();
798
+ });
799
+ });
800
+ });
801
+ describe('handle invalid state transitions', () => {
802
+ const { createRouter } = setupRouterMock();
803
+ const pageRef = createPageRef();
804
+ it('onStateChanged should only be called with "stopped" after status "done"', async () => {
805
+ const expected = ['running', 'done', 'stopped'];
806
+ expect.assertions(expected.length + 2);
807
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
808
+ const service = setup.run();
809
+ const { onStateChanged } = mockPrefetchConfig;
810
+ jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, _inputs, callbacks) => {
811
+ // prefetch in running
812
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done'); // allowed
813
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running'); // ignored
814
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done'); // ignored
815
+ service.stop();
816
+ service.onUnexpectedCondition('Should be ignored'); // ignored
817
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running'); // ignored
818
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done'); // ignored
819
+ return { start: jest.fn(), stop: jest.fn() };
820
+ });
821
+ return await waitForExpect(() => {
822
+ expect(onStateChanged).toBeCalledTimes(expected.length);
823
+ expected.forEach((expectedState, idx) => {
824
+ expect(onStateChanged).toHaveBeenNthCalledWith(idx + 1, expect.objectContaining({
825
+ state: expectedState,
826
+ }));
827
+ });
828
+ expect(service.resolutionGroups[0].bulkResolver).not.toBe(undefined);
829
+ onStateChanged.mockClear();
830
+ service.stop();
831
+ }, 0);
832
+ });
833
+ it('onStateChanged "running" -> "error" -> "done" -> "stopped"', async () => {
834
+ const expected = ['running', 'error', 'done', 'stopped'];
835
+ expect.assertions(expected.length + 2);
836
+ const setup = setupPrefetch(createRouter, [pageRef], mockPrefetchConfig);
837
+ const service = setup.run();
838
+ const { onStateChanged } = mockPrefetchConfig;
839
+ jest.spyOn(ResolverApi, 'getBulkAdgResolver').mockImplementationOnce((_adg, _inputs, callbacks) => {
840
+ // prefetch in running
841
+ service.onUnexpectedCondition('should go through'); // allowed
842
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running'); // ignored
843
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done'); // allowed
844
+ service.onUnexpectedCondition('Should be ignored 1'); // ignored
845
+ service.stop(); // allowed
846
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'done'); // ignored
847
+ service.onUnexpectedCondition('Should be ignored 2'); // ignored
848
+ invokeCallbackWithState(callbacks.bulkResolutionStatusCb, 'running'); // ignored
849
+ return { start: jest.fn(), stop: jest.fn() };
850
+ });
851
+ return await waitForExpect(() => {
852
+ expect(onStateChanged).toBeCalledTimes(expected.length);
853
+ expected.forEach((expectedState, idx) => {
854
+ expect(onStateChanged).toHaveBeenNthCalledWith(idx + 1, expect.objectContaining({
855
+ state: expectedState,
856
+ }));
857
+ });
858
+ expect(service.resolutionGroups[0].bulkResolver).not.toBe(undefined);
859
+ onStateChanged.mockClear();
860
+ service.stop();
861
+ }, 0);
862
+ });
863
+ });
864
+ });
865
+ //# sourceMappingURL=prefetchService.spec.js.map
@@ -0,0 +1,26 @@
1
+ /// <reference types="jest" />
2
+ import { PageReference, Router, RouterConfig, RoutingResult, Module } from 'lwr/router';
3
+ import { createRouter } from '@lwrjs/router';
4
+ import { PrefetchConfig } from '../modules/komaci/prefetchTypes/prefetchTypes';
5
+ declare type RouterModule = {
6
+ createRouter: typeof createRouter;
7
+ };
8
+ export declare function defaultRoutingResult(address: PageReference): RoutingResult;
9
+ export declare function setupRouterMock(resolveAddress?: (address: PageReference) => Partial<RoutingResult>): RouterModule;
10
+ export declare function createPageRef(apiName?: string, recordId?: string, state?: Record<string, string | null>): PageReference;
11
+ export declare function createAdgModule(): Module;
12
+ export declare function createRoutingResult(address: PageReference, adgModule: Module | false): RoutingResult;
13
+ export declare function setupPrefetch(createRouter: (config: RouterConfig) => Router<PageReference>, pageRefs: PageReference[] | undefined, config: PrefetchConfig): any;
14
+ export declare const mockPrefetchConfig: {
15
+ onStateChanged: jest.Mock<any, any>;
16
+ onAddressProcessed: jest.Mock<any, any>;
17
+ downloadImage: undefined;
18
+ instrumentationContext: {
19
+ rootId: string;
20
+ isRootActivitySampled: boolean;
21
+ };
22
+ };
23
+ export declare const mockPrefetchConfigStatusError: PrefetchConfig;
24
+ export declare const mockPrefetchConfigStateError: PrefetchConfig;
25
+ export {};
26
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1,118 @@
1
+ import { createRouter } from '@lwrjs/router';
2
+ import { getPrefetchService } from '../modules/komaci/prefetch/prefetch';
3
+ import registerAdgFunction from 'komaci/registerAdgFunction';
4
+ export function defaultRoutingResult(address) {
5
+ return createRoutingResult(address, createAdgModule());
6
+ }
7
+ export function setupRouterMock(resolveAddress = defaultRoutingResult) {
8
+ return {
9
+ createRouter: createRouter.mockImplementation((config) => {
10
+ return {
11
+ config,
12
+ resolveView: jest
13
+ .fn()
14
+ .mockImplementation((address) => {
15
+ const { viewset } = resolveAddress(address);
16
+ return Promise.resolve({
17
+ viewset,
18
+ });
19
+ }),
20
+ };
21
+ }),
22
+ };
23
+ }
24
+ export function createPageRef(apiName = 'action1', recordId = '1', state = {}) {
25
+ return {
26
+ type: 'standard__quickAction',
27
+ attributes: {
28
+ apiName,
29
+ recordId,
30
+ objectApiName: 'Account',
31
+ },
32
+ state,
33
+ };
34
+ }
35
+ export function createAdgModule() {
36
+ const emptyAdg = {
37
+ parentClass: undefined,
38
+ properties: {},
39
+ functions: [],
40
+ composition: () => [],
41
+ };
42
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
43
+ const mockAdgModuleFunction = (fct) => emptyAdg;
44
+ return { default: registerAdgFunction(mockAdgModuleFunction) };
45
+ }
46
+ export function createRoutingResult(address, adgModule) {
47
+ const { state, attributes, attributes: { apiName, recordId, objectApiName }, type, } = address;
48
+ const viewset = (adgModule
49
+ ? {
50
+ default: {
51
+ module: () => Promise.resolve(adgModule),
52
+ specifier: '@salesforce/action/' + address.attributes.apiName,
53
+ },
54
+ }
55
+ : {});
56
+ return {
57
+ viewset,
58
+ pathMatch: `/${type}/${objectApiName}/${recordId}/${apiName}`,
59
+ route: {
60
+ id: type,
61
+ attributes: attributes,
62
+ state: state,
63
+ pageReference: address,
64
+ },
65
+ routeDefinition: {},
66
+ };
67
+ }
68
+ export function setupPrefetch(createRouter, pageRefs = [], config) {
69
+ const router = createRouter({});
70
+ return jest.fn(() => ({
71
+ createRouter,
72
+ pageRefs,
73
+ config,
74
+ run: () => {
75
+ return getPrefetchService(router, pageRefs, config);
76
+ },
77
+ }))();
78
+ }
79
+ export const mockPrefetchConfig = jest.fn(() => ({
80
+ onStateChanged: jest.fn(),
81
+ // .mockImplementation((status) =>
82
+ // // eslint-disable-next-line no-console
83
+ // console.log('onStateChanged', status.state, status.message),
84
+ // ),
85
+ onAddressProcessed: jest.fn(),
86
+ // .mockImplementation((status) =>
87
+ // // eslint-disable-next-line no-console
88
+ // console.log('onAddresProcessed', status),
89
+ // ),
90
+ downloadImage: undefined,
91
+ instrumentationContext: {
92
+ rootId: 'abcd-1234',
93
+ isRootActivitySampled: true,
94
+ },
95
+ }))();
96
+ export const mockPrefetchConfigStatusError = {
97
+ onStateChanged: jest.fn(),
98
+ onAddressProcessed: jest.fn().mockImplementation(() => {
99
+ throw new Error(`Unexpected state status.`);
100
+ }),
101
+ downloadImage: undefined,
102
+ instrumentationContext: {
103
+ rootId: 'abcd-1234',
104
+ isRootActivitySampled: true,
105
+ },
106
+ };
107
+ export const mockPrefetchConfigStateError = {
108
+ onStateChanged: jest.fn().mockImplementation(() => {
109
+ throw new Error(`Unexpected state transition.`);
110
+ }),
111
+ onAddressProcessed: jest.fn(),
112
+ downloadImage: undefined,
113
+ instrumentationContext: {
114
+ rootId: 'abcd-1234',
115
+ isRootActivitySampled: true,
116
+ },
117
+ };
118
+ //# sourceMappingURL=utils.js.map
@@ -32,7 +32,6 @@ export class PrefetchService {
32
32
  this._instrumentation = getInstrumentation('komaci');
33
33
  this._activity = this._instrumentation.startActivity('prefetch', this.apiOptions);
34
34
  this._size = addresses.length;
35
- //FIXME: to use o11y.startActivity() when o11y available
36
35
  this._startTime = Date.now();
37
36
  this.prefetch(addresses);
38
37
  }
@@ -57,7 +56,7 @@ export class PrefetchService {
57
56
  return this.onRoutingResult(address, destination);
58
57
  })
59
58
  .then((value) => {
60
- this._instrumentation.log(prefetchSchema, userSchemaData, this.apiOptions);
59
+ this._instrumentation.incrementCounter('prefetch.route-success', 1);
61
60
  return value;
62
61
  })
63
62
  .catch((err) => {
@@ -1,5 +1,5 @@
1
1
  import type { PageReference } from 'lwr/router';
2
- import type { ResolverExecutionState, AdgInput, AdgModule, IBulkResolver } from '@komaci/resolver';
2
+ import type { ResolverExecutionState, AdgInput, AdgModuleExport, IBulkResolver } from '@komaci/resolver';
3
3
  import { InstrumentationContext } from 'o11y/dist/modules/o11y/client/interfaces';
4
4
  export declare const ERROR_PREFIX = "[komaci prefetch]";
5
5
  /**
@@ -8,7 +8,7 @@ export declare const ERROR_PREFIX = "[komaci prefetch]";
8
8
  export declare type AdgRoutingResult<TAddress = PageReference> = {
9
9
  address: TAddress;
10
10
  success: boolean;
11
- adgModule?: AdgModule;
11
+ adgModule?: AdgModuleExport;
12
12
  reason?: string;
13
13
  };
14
14
  /**
@@ -26,6 +26,7 @@ export declare type AdgResolutionGroup<TAddress = PageReference> = {
26
26
  };
27
27
  export interface IPrefetchService {
28
28
  stop(): void;
29
+ getState(): PrefetchState;
29
30
  }
30
31
  export declare enum ResolutionStatusState {
31
32
  running = "running",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/prefetch",
3
- "version": "242.2.4",
3
+ "version": "244.0.0",
4
4
  "description": "Komaci prefetch service.",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {
@@ -26,14 +26,14 @@
26
26
  "build/**/*.d.ts"
27
27
  ],
28
28
  "dependencies": {
29
- "@komaci/module-shared": "242.2.4",
30
- "@komaci/resolver": "242.2.4",
29
+ "@komaci/module-shared": "244.0.0",
30
+ "@komaci/resolver": "244.0.0",
31
31
  "@lwrjs/router": "0.6.0-alpha.15",
32
- "o11y": "^240.7.0",
33
- "o11y_schema": "^240.11.0"
32
+ "o11y": "^244.0.0",
33
+ "o11y_schema": "^244.0.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@komaci/types": "242.2.4",
36
+ "@komaci/types": "244.0.0",
37
37
  "wait-for-expect": "^3.0.2"
38
38
  }
39
39
  }