@docknetwork/wallet-sdk-core 1.5.14 → 1.7.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.
- package/generate-docs.js +33 -0
- package/jsdoc.conf.json +28 -0
- package/lib/biometric-provider.d.ts +123 -31
- package/lib/biometric-provider.d.ts.map +1 -1
- package/lib/biometric-provider.js +146 -7
- package/lib/biometric-provider.js.map +1 -1
- package/lib/cloud-wallet.d.ts +7 -3
- package/lib/cloud-wallet.d.ts.map +1 -1
- package/lib/cloud-wallet.js +29 -18
- package/lib/cloud-wallet.js.map +1 -1
- package/lib/credential-provider.d.ts +58 -33
- package/lib/credential-provider.d.ts.map +1 -1
- package/lib/credential-provider.js +214 -13
- package/lib/credential-provider.js.map +1 -1
- package/lib/credentials/oidvc.js +6 -7
- package/lib/credentials/oidvc.js.map +1 -1
- package/lib/did-provider.d.ts +102 -36
- package/lib/did-provider.d.ts.map +1 -1
- package/lib/did-provider.js +186 -28
- package/lib/did-provider.js.map +1 -1
- package/lib/ecosystem-tools.js +5 -6
- package/lib/ecosystem-tools.js.map +1 -1
- package/lib/helpers.js +6 -6
- package/lib/helpers.js.map +1 -1
- package/lib/message-provider.d.ts +39 -13
- package/lib/message-provider.d.ts.map +1 -1
- package/lib/message-provider.js +146 -20
- package/lib/message-provider.js.map +1 -1
- package/lib/messages/message-helpers.js +6 -6
- package/lib/messages/message-helpers.js.map +1 -1
- package/lib/network-resolver.d.ts +1 -1
- package/lib/network-resolver.js +5 -5
- package/lib/network-resolver.js.map +1 -1
- package/lib/qr-handlers/builtin/index.d.ts +30 -0
- package/lib/qr-handlers/builtin/index.d.ts.map +1 -0
- package/lib/qr-handlers/builtin/index.js +46 -0
- package/lib/qr-handlers/builtin/index.js.map +1 -0
- package/lib/qr-handlers/builtin/oid4vc-handler.d.ts +137 -0
- package/lib/qr-handlers/builtin/oid4vc-handler.d.ts.map +1 -0
- package/lib/qr-handlers/builtin/oid4vc-handler.js +134 -0
- package/lib/qr-handlers/builtin/oid4vc-handler.js.map +1 -0
- package/lib/qr-handlers/index.d.ts +76 -0
- package/lib/qr-handlers/index.d.ts.map +1 -0
- package/lib/qr-handlers/index.js +92 -0
- package/lib/qr-handlers/index.js.map +1 -0
- package/lib/qr-handlers/processor.d.ts +110 -0
- package/lib/qr-handlers/processor.d.ts.map +1 -0
- package/lib/qr-handlers/processor.js +251 -0
- package/lib/qr-handlers/processor.js.map +1 -0
- package/lib/qr-handlers/types.d.ts +205 -0
- package/lib/qr-handlers/types.d.ts.map +1 -0
- package/lib/qr-handlers/types.js +10 -0
- package/lib/qr-handlers/types.js.map +1 -0
- package/lib/types.d.ts +610 -14
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +16 -0
- package/lib/types.js.map +1 -1
- package/lib/verification-controller.d.ts +0 -1
- package/lib/verification-controller.d.ts.map +1 -1
- package/lib/verification-controller.js +12 -5
- package/lib/verification-controller.js.map +1 -1
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts +0 -1
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.d.ts.map +1 -1
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js +3 -3
- package/lib/wallet-to-wallet-verification/walletToWalletVerificationProvider.js.map +1 -1
- package/lib/wallet-wasm.d.ts.map +1 -1
- package/lib/wallet-wasm.js +13 -14
- package/lib/wallet-wasm.js.map +1 -1
- package/lib/wallet.d.ts +36 -20
- package/lib/wallet.d.ts.map +1 -1
- package/lib/wallet.js +174 -28
- package/lib/wallet.js.map +1 -1
- package/package.json +17 -9
- package/src/biometric-provider.ts +157 -42
- package/src/cloud-wallet.ts +13 -0
- package/src/credential-provider.test.ts +191 -1
- package/src/credential-provider.ts +208 -27
- package/src/did-provider.ts +183 -34
- package/src/message-provider.ts +148 -34
- package/src/qr-handlers/builtin/index.ts +30 -0
- package/src/qr-handlers/builtin/oid4vc-handler.ts +198 -0
- package/src/qr-handlers/index.ts +76 -0
- package/src/qr-handlers/processor.test.ts +514 -0
- package/src/qr-handlers/processor.ts +311 -0
- package/src/qr-handlers/types.ts +228 -0
- package/src/types.ts +666 -11
- package/src/verification-controller.test.ts +1 -2
- package/src/verification-controller.ts +9 -1
- package/src/wallet-wasm.ts +1 -3
- package/src/wallet.ts +173 -24
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import {DefaultQRCodeProcessor, createQRCodeProcessor} from './processor';
|
|
2
|
+
import {
|
|
3
|
+
QRCodeContext,
|
|
4
|
+
QRCodeHandler,
|
|
5
|
+
QRCodeHandlerResult,
|
|
6
|
+
} from './types';
|
|
7
|
+
|
|
8
|
+
describe('DefaultQRCodeProcessor', () => {
|
|
9
|
+
let processor: DefaultQRCodeProcessor;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
processor = new DefaultQRCodeProcessor();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe('Handler Registration', () => {
|
|
16
|
+
it('should register a handler successfully', () => {
|
|
17
|
+
const handler: QRCodeHandler = {
|
|
18
|
+
id: 'test-handler',
|
|
19
|
+
canHandle: () => true,
|
|
20
|
+
handle: async () => ({success: true}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
processor.registerHandler(handler);
|
|
24
|
+
expect(processor.getHandlers()).toHaveLength(1);
|
|
25
|
+
expect(processor.getHandler('test-handler')).toBe(handler);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should throw error when registering handler with duplicate ID', () => {
|
|
29
|
+
const handler1: QRCodeHandler = {
|
|
30
|
+
id: 'test-handler',
|
|
31
|
+
canHandle: () => true,
|
|
32
|
+
handle: async () => ({success: true}),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handler2: QRCodeHandler = {
|
|
36
|
+
id: 'test-handler',
|
|
37
|
+
canHandle: () => true,
|
|
38
|
+
handle: async () => ({success: true}),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
processor.registerHandler(handler1);
|
|
42
|
+
expect(() => processor.registerHandler(handler2)).toThrow(
|
|
43
|
+
'Handler with id "test-handler" is already registered',
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should unregister a handler successfully', () => {
|
|
48
|
+
const handler: QRCodeHandler = {
|
|
49
|
+
id: 'test-handler',
|
|
50
|
+
canHandle: () => true,
|
|
51
|
+
handle: async () => ({success: true}),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
processor.registerHandler(handler);
|
|
55
|
+
expect(processor.getHandlers()).toHaveLength(1);
|
|
56
|
+
|
|
57
|
+
const removed = processor.unregisterHandler('test-handler');
|
|
58
|
+
expect(removed).toBe(true);
|
|
59
|
+
expect(processor.getHandlers()).toHaveLength(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should return false when unregistering non-existent handler', () => {
|
|
63
|
+
const removed = processor.unregisterHandler('non-existent');
|
|
64
|
+
expect(removed).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should clear all handlers', () => {
|
|
68
|
+
processor.registerHandler({
|
|
69
|
+
id: 'handler-1',
|
|
70
|
+
canHandle: () => true,
|
|
71
|
+
handle: async () => ({success: true}),
|
|
72
|
+
});
|
|
73
|
+
processor.registerHandler({
|
|
74
|
+
id: 'handler-2',
|
|
75
|
+
canHandle: () => true,
|
|
76
|
+
handle: async () => ({success: true}),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(processor.getHandlers()).toHaveLength(2);
|
|
80
|
+
processor.clearHandlers();
|
|
81
|
+
expect(processor.getHandlers()).toHaveLength(0);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('Handler Priority', () => {
|
|
86
|
+
it('should sort handlers by priority', () => {
|
|
87
|
+
const handler1: QRCodeHandler = {
|
|
88
|
+
id: 'handler-1',
|
|
89
|
+
priority: 50,
|
|
90
|
+
canHandle: () => true,
|
|
91
|
+
handle: async () => ({success: true}),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const handler2: QRCodeHandler = {
|
|
95
|
+
id: 'handler-2',
|
|
96
|
+
priority: 10,
|
|
97
|
+
canHandle: () => true,
|
|
98
|
+
handle: async () => ({success: true}),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const handler3: QRCodeHandler = {
|
|
102
|
+
id: 'handler-3',
|
|
103
|
+
priority: 30,
|
|
104
|
+
canHandle: () => true,
|
|
105
|
+
handle: async () => ({success: true}),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
processor.registerHandler(handler1);
|
|
109
|
+
processor.registerHandler(handler2);
|
|
110
|
+
processor.registerHandler(handler3);
|
|
111
|
+
|
|
112
|
+
const handlers = processor.getHandlers();
|
|
113
|
+
expect(handlers[0].id).toBe('handler-2');
|
|
114
|
+
expect(handlers[1].id).toBe('handler-3');
|
|
115
|
+
expect(handlers[2].id).toBe('handler-1');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should use default priority of 100 if not specified', () => {
|
|
119
|
+
const handler1: QRCodeHandler = {
|
|
120
|
+
id: 'handler-1',
|
|
121
|
+
canHandle: () => true,
|
|
122
|
+
handle: async () => ({success: true}),
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const handler2: QRCodeHandler = {
|
|
126
|
+
id: 'handler-2',
|
|
127
|
+
priority: 50,
|
|
128
|
+
canHandle: () => true,
|
|
129
|
+
handle: async () => ({success: true}),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
processor.registerHandler(handler1);
|
|
133
|
+
processor.registerHandler(handler2);
|
|
134
|
+
|
|
135
|
+
const handlers = processor.getHandlers();
|
|
136
|
+
expect(handlers[0].id).toBe('handler-2'); // priority 50
|
|
137
|
+
expect(handlers[1].id).toBe('handler-1'); // default priority 100
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('QR Code Processing', () => {
|
|
142
|
+
it('should process QR code with matching handler', async () => {
|
|
143
|
+
const handler: QRCodeHandler = {
|
|
144
|
+
id: 'test-handler',
|
|
145
|
+
canHandle: (context) => context.data.startsWith('test://'),
|
|
146
|
+
handle: async (context) => ({
|
|
147
|
+
success: true,
|
|
148
|
+
data: {processed: context.data},
|
|
149
|
+
}),
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
processor.registerHandler(handler);
|
|
153
|
+
const result = await processor.process('test://some-data');
|
|
154
|
+
|
|
155
|
+
expect(result.success).toBe(true);
|
|
156
|
+
expect(result.data).toEqual({processed: 'test://some-data'});
|
|
157
|
+
expect(result.metadata?.handlerId).toBe('test-handler');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should fail when no handlers are registered', async () => {
|
|
161
|
+
const result = await processor.process('test://data');
|
|
162
|
+
|
|
163
|
+
expect(result.success).toBe(false);
|
|
164
|
+
expect(result.error?.message).toBe('No handlers registered');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should fail when no handler can process the data', async () => {
|
|
168
|
+
const handler: QRCodeHandler = {
|
|
169
|
+
id: 'test-handler',
|
|
170
|
+
canHandle: () => false,
|
|
171
|
+
handle: async () => ({success: true}),
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
processor.registerHandler(handler);
|
|
175
|
+
const result = await processor.process('test://data');
|
|
176
|
+
|
|
177
|
+
expect(result.success).toBe(false);
|
|
178
|
+
expect(result.error?.message).toContain('No handler could process');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should try handlers in priority order', async () => {
|
|
182
|
+
const executionOrder: string[] = [];
|
|
183
|
+
|
|
184
|
+
const handler1: QRCodeHandler = {
|
|
185
|
+
id: 'handler-1',
|
|
186
|
+
priority: 50,
|
|
187
|
+
canHandle: () => true,
|
|
188
|
+
handle: async () => {
|
|
189
|
+
executionOrder.push('handler-1');
|
|
190
|
+
return {success: false};
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const handler2: QRCodeHandler = {
|
|
195
|
+
id: 'handler-2',
|
|
196
|
+
priority: 10,
|
|
197
|
+
canHandle: () => true,
|
|
198
|
+
handle: async () => {
|
|
199
|
+
executionOrder.push('handler-2');
|
|
200
|
+
return {success: true};
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
processor.registerHandler(handler1);
|
|
205
|
+
processor.registerHandler(handler2);
|
|
206
|
+
|
|
207
|
+
await processor.process('test://data');
|
|
208
|
+
|
|
209
|
+
expect(executionOrder).toEqual(['handler-2', 'handler-1']);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('should stop on first successful handler by default', async () => {
|
|
213
|
+
const executionOrder: string[] = [];
|
|
214
|
+
|
|
215
|
+
const handler1: QRCodeHandler = {
|
|
216
|
+
id: 'handler-1',
|
|
217
|
+
priority: 10,
|
|
218
|
+
canHandle: () => true,
|
|
219
|
+
handle: async () => {
|
|
220
|
+
executionOrder.push('handler-1');
|
|
221
|
+
return {success: true};
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const handler2: QRCodeHandler = {
|
|
226
|
+
id: 'handler-2',
|
|
227
|
+
priority: 20,
|
|
228
|
+
canHandle: () => true,
|
|
229
|
+
handle: async () => {
|
|
230
|
+
executionOrder.push('handler-2');
|
|
231
|
+
return {success: true};
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
processor.registerHandler(handler1);
|
|
236
|
+
processor.registerHandler(handler2);
|
|
237
|
+
|
|
238
|
+
await processor.process('test://data');
|
|
239
|
+
|
|
240
|
+
expect(executionOrder).toEqual(['handler-1']);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should continue to other handlers when stopOnFirstSuccess is false', async () => {
|
|
244
|
+
const executionOrder: string[] = [];
|
|
245
|
+
|
|
246
|
+
const handler1: QRCodeHandler = {
|
|
247
|
+
id: 'handler-1',
|
|
248
|
+
priority: 10,
|
|
249
|
+
canHandle: () => true,
|
|
250
|
+
handle: async () => {
|
|
251
|
+
executionOrder.push('handler-1');
|
|
252
|
+
return {success: true};
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const handler2: QRCodeHandler = {
|
|
257
|
+
id: 'handler-2',
|
|
258
|
+
priority: 20,
|
|
259
|
+
canHandle: () => true,
|
|
260
|
+
handle: async () => {
|
|
261
|
+
executionOrder.push('handler-2');
|
|
262
|
+
return {success: true};
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
processor.registerHandler(handler1);
|
|
267
|
+
processor.registerHandler(handler2);
|
|
268
|
+
|
|
269
|
+
await processor.process('test://data', {stopOnFirstSuccess: false});
|
|
270
|
+
|
|
271
|
+
expect(executionOrder).toEqual(['handler-1', 'handler-2']);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should skip handlers that cannot handle the data', async () => {
|
|
275
|
+
const executionOrder: string[] = [];
|
|
276
|
+
|
|
277
|
+
const handler1: QRCodeHandler = {
|
|
278
|
+
id: 'handler-1',
|
|
279
|
+
priority: 10,
|
|
280
|
+
canHandle: () => false,
|
|
281
|
+
handle: async () => {
|
|
282
|
+
executionOrder.push('handler-1');
|
|
283
|
+
return {success: true};
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const handler2: QRCodeHandler = {
|
|
288
|
+
id: 'handler-2',
|
|
289
|
+
priority: 20,
|
|
290
|
+
canHandle: () => true,
|
|
291
|
+
handle: async () => {
|
|
292
|
+
executionOrder.push('handler-2');
|
|
293
|
+
return {success: true};
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
processor.registerHandler(handler1);
|
|
298
|
+
processor.registerHandler(handler2);
|
|
299
|
+
|
|
300
|
+
await processor.process('test://data');
|
|
301
|
+
|
|
302
|
+
expect(executionOrder).toEqual(['handler-2']);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should handle async canHandle method', async () => {
|
|
306
|
+
const handler: QRCodeHandler = {
|
|
307
|
+
id: 'test-handler',
|
|
308
|
+
canHandle: async (context) => {
|
|
309
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
310
|
+
return context.data.startsWith('test://');
|
|
311
|
+
},
|
|
312
|
+
handle: async () => ({success: true}),
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
processor.registerHandler(handler);
|
|
316
|
+
const result = await processor.process('test://data');
|
|
317
|
+
|
|
318
|
+
expect(result.success).toBe(true);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('should continue to next handler when one throws error', async () => {
|
|
322
|
+
const handler1: QRCodeHandler = {
|
|
323
|
+
id: 'handler-1',
|
|
324
|
+
priority: 10,
|
|
325
|
+
canHandle: () => true,
|
|
326
|
+
handle: async () => {
|
|
327
|
+
throw new Error('Handler 1 error');
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const handler2: QRCodeHandler = {
|
|
332
|
+
id: 'handler-2',
|
|
333
|
+
priority: 20,
|
|
334
|
+
canHandle: () => true,
|
|
335
|
+
handle: async () => ({success: true, data: 'processed'}),
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
processor.registerHandler(handler1);
|
|
339
|
+
processor.registerHandler(handler2);
|
|
340
|
+
|
|
341
|
+
const result = await processor.process('test://data');
|
|
342
|
+
|
|
343
|
+
expect(result.success).toBe(true);
|
|
344
|
+
expect(result.data).toBe('processed');
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
describe('Context Preparation', () => {
|
|
349
|
+
it('should prepare context with JSON data', async () => {
|
|
350
|
+
const jsonData = {type: 'credential', id: '123'};
|
|
351
|
+
const handler: QRCodeHandler = {
|
|
352
|
+
id: 'test-handler',
|
|
353
|
+
canHandle: (context) => context.jsonData?.type === 'credential',
|
|
354
|
+
handle: async (context) => ({success: true, data: context.jsonData}),
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
processor.registerHandler(handler);
|
|
358
|
+
const result = await processor.process(JSON.stringify(jsonData));
|
|
359
|
+
|
|
360
|
+
expect(result.success).toBe(true);
|
|
361
|
+
expect(result.data).toEqual(jsonData);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should prepare context with URL', async () => {
|
|
365
|
+
const handler: QRCodeHandler = {
|
|
366
|
+
id: 'test-handler',
|
|
367
|
+
canHandle: (context) => !!context.url,
|
|
368
|
+
handle: async (context) => ({success: true, data: {url: context.url}}),
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
processor.registerHandler(handler);
|
|
372
|
+
const result = await processor.process('https://example.com/credential');
|
|
373
|
+
|
|
374
|
+
expect(result.success).toBe(true);
|
|
375
|
+
expect(result.data.url).toBe('https://example.com/credential');
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('should use custom prepareContext function', async () => {
|
|
379
|
+
const handler: QRCodeHandler = {
|
|
380
|
+
id: 'test-handler',
|
|
381
|
+
canHandle: (context) => context.metadata?.custom === true,
|
|
382
|
+
handle: async (context) => ({success: true, data: context.metadata}),
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
processor.registerHandler(handler);
|
|
386
|
+
|
|
387
|
+
const result = await processor.process('test://data', {
|
|
388
|
+
prepareContext: async (data) => ({
|
|
389
|
+
data,
|
|
390
|
+
metadata: {custom: true, value: 'test'},
|
|
391
|
+
}),
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
expect(result.success).toBe(true);
|
|
395
|
+
expect(result.data).toEqual({custom: true, value: 'test'});
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
describe('Callbacks', () => {
|
|
400
|
+
it('should call onSuccess callback when handler succeeds', async () => {
|
|
401
|
+
const onSuccess = jest.fn();
|
|
402
|
+
const handler: QRCodeHandler = {
|
|
403
|
+
id: 'test-handler',
|
|
404
|
+
canHandle: () => true,
|
|
405
|
+
handle: async () => ({success: true, data: 'result'}),
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
processor.registerHandler(handler);
|
|
409
|
+
await processor.process('test://data', {onSuccess});
|
|
410
|
+
|
|
411
|
+
expect(onSuccess).toHaveBeenCalledWith(
|
|
412
|
+
expect.objectContaining({success: true, data: 'result'}),
|
|
413
|
+
handler,
|
|
414
|
+
);
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('should call onError callback when handler throws', async () => {
|
|
418
|
+
const onError = jest.fn();
|
|
419
|
+
const error = new Error('Handler error');
|
|
420
|
+
const handler: QRCodeHandler = {
|
|
421
|
+
id: 'test-handler',
|
|
422
|
+
canHandle: () => true,
|
|
423
|
+
handle: async () => {
|
|
424
|
+
throw error;
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
processor.registerHandler(handler);
|
|
429
|
+
await processor.process('test://data', {onError});
|
|
430
|
+
|
|
431
|
+
expect(onError).toHaveBeenCalledWith(error, handler);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it('should not fail if callback throws error', async () => {
|
|
435
|
+
const onSuccess = jest.fn(() => {
|
|
436
|
+
throw new Error('Callback error');
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const handler: QRCodeHandler = {
|
|
440
|
+
id: 'test-handler',
|
|
441
|
+
canHandle: () => true,
|
|
442
|
+
handle: async () => ({success: true}),
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
processor.registerHandler(handler);
|
|
446
|
+
const result = await processor.process('test://data', {onSuccess});
|
|
447
|
+
|
|
448
|
+
expect(result.success).toBe(true);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
describe('Timeout', () => {
|
|
453
|
+
it('should timeout handler that takes too long', async () => {
|
|
454
|
+
const handler: QRCodeHandler = {
|
|
455
|
+
id: 'slow-handler',
|
|
456
|
+
canHandle: () => true,
|
|
457
|
+
handle: async () => {
|
|
458
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
459
|
+
return {success: true};
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
processor.registerHandler(handler);
|
|
464
|
+
const result = await processor.process('test://data', {timeout: 100});
|
|
465
|
+
|
|
466
|
+
expect(result.success).toBe(false);
|
|
467
|
+
expect(result.error?.message).toContain('timed out');
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('should use default timeout of 30 seconds', async () => {
|
|
471
|
+
const handler: QRCodeHandler = {
|
|
472
|
+
id: 'test-handler',
|
|
473
|
+
canHandle: () => true,
|
|
474
|
+
handle: async () => {
|
|
475
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
476
|
+
return {success: true};
|
|
477
|
+
},
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
processor.registerHandler(handler);
|
|
481
|
+
const result = await processor.process('test://data');
|
|
482
|
+
|
|
483
|
+
expect(result.success).toBe(true);
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
describe('Factory Function', () => {
|
|
488
|
+
it('should create processor with handlers', () => {
|
|
489
|
+
const handler1: QRCodeHandler = {
|
|
490
|
+
id: 'handler-1',
|
|
491
|
+
canHandle: () => true,
|
|
492
|
+
handle: async () => ({success: true}),
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const handler2: QRCodeHandler = {
|
|
496
|
+
id: 'handler-2',
|
|
497
|
+
canHandle: () => true,
|
|
498
|
+
handle: async () => ({success: true}),
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const proc = createQRCodeProcessor([handler1, handler2]);
|
|
502
|
+
|
|
503
|
+
expect(proc.getHandlers()).toHaveLength(2);
|
|
504
|
+
expect(proc.getHandler('handler-1')).toBeDefined();
|
|
505
|
+
expect(proc.getHandler('handler-2')).toBeDefined();
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
it('should create processor without handlers', () => {
|
|
509
|
+
const proc = createQRCodeProcessor();
|
|
510
|
+
|
|
511
|
+
expect(proc.getHandlers()).toHaveLength(0);
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
});
|