@notabene/javascript-sdk 2.0.0-next.9 → 2.0.1
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/LICENSE.md +21 -0
- package/README.md +477 -111
- package/dist/js/notabene.js +1 -0
- package/dist/notabene.cjs +1 -1
- package/dist/notabene.js +286 -110
- package/package.json +34 -25
- package/src/__tests__/notabene.test.ts +113 -2
- package/src/arbitraries.ts +0 -13
- package/src/components/EmbeddedComponent.ts +125 -63
- package/src/components/__tests__/EmbeddedComponent.test.ts +402 -32
- package/src/ivms/types.ts +177 -140
- package/src/locales.ts +48 -0
- package/src/notabene.ts +199 -63
- package/src/types.ts +773 -150
- package/src/utils/MessageEventManager.ts +70 -9
- package/src/utils/__tests__/MessageEventManager.test.ts +29 -5
- package/src/utils/__tests__/urls.test.ts +112 -0
- package/src/utils/arbitraries.ts +219 -1
- package/src/utils/urls.ts +30 -5
- package/dist/notabene.d.ts +0 -780
- package/dist/tsdoc-metadata.json +0 -11
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AgentType,
|
|
4
|
+
CMType,
|
|
5
|
+
HMType,
|
|
6
|
+
type HostMessage,
|
|
7
|
+
type Transaction,
|
|
8
|
+
type TransactionOptions,
|
|
9
|
+
type Withdrawal,
|
|
10
|
+
} from '../../types';
|
|
11
|
+
import { MessageEventManager } from '../../utils/MessageEventManager';
|
|
3
12
|
import EmbeddedComponent from '../EmbeddedComponent';
|
|
4
13
|
|
|
5
14
|
const url = 'https://example.com';
|
|
@@ -8,9 +17,11 @@ const value: Partial<Transaction> = { amountDecimal: 100 };
|
|
|
8
17
|
|
|
9
18
|
describe('EmbeddedComponent', () => {
|
|
10
19
|
describe('creation', () => {
|
|
11
|
-
let component: EmbeddedComponent
|
|
20
|
+
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
12
21
|
beforeEach(() => {
|
|
13
|
-
component = new EmbeddedComponent(url, {
|
|
22
|
+
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(url, {
|
|
23
|
+
amountDecimal: 100,
|
|
24
|
+
});
|
|
14
25
|
});
|
|
15
26
|
|
|
16
27
|
test('sets value', () => {
|
|
@@ -27,7 +38,6 @@ describe('EmbeddedComponent', () => {
|
|
|
27
38
|
let parentElement: HTMLElement;
|
|
28
39
|
let iframe: HTMLIFrameElement;
|
|
29
40
|
let window: Window;
|
|
30
|
-
let iframeWindow: Window;
|
|
31
41
|
|
|
32
42
|
beforeEach(() => {
|
|
33
43
|
parentElement = {
|
|
@@ -37,7 +47,10 @@ describe('EmbeddedComponent', () => {
|
|
|
37
47
|
iframe = {
|
|
38
48
|
style: {},
|
|
39
49
|
src: '',
|
|
40
|
-
contentWindow:
|
|
50
|
+
contentWindow: {
|
|
51
|
+
focus: vi.fn(),
|
|
52
|
+
} as unknown as Window,
|
|
53
|
+
remove: vi.fn(),
|
|
41
54
|
setAttribute: vi.fn(),
|
|
42
55
|
addEventListener: vi.fn(),
|
|
43
56
|
} as unknown as HTMLIFrameElement;
|
|
@@ -60,14 +73,20 @@ describe('EmbeddedComponent', () => {
|
|
|
60
73
|
});
|
|
61
74
|
|
|
62
75
|
test('mount', () => {
|
|
63
|
-
const component = new EmbeddedComponent
|
|
76
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
77
|
+
url,
|
|
78
|
+
value,
|
|
79
|
+
);
|
|
64
80
|
component.mount(parentId);
|
|
65
|
-
expect(iframe?.src).toBe(url);
|
|
81
|
+
expect(iframe?.src).toBe(url + '&embedded=true');
|
|
66
82
|
expect(parentElement.appendChild).toHaveBeenCalledWith(iframe);
|
|
67
83
|
});
|
|
68
84
|
|
|
69
85
|
test('on', () => {
|
|
70
|
-
const component = new EmbeddedComponent
|
|
86
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
87
|
+
url,
|
|
88
|
+
value,
|
|
89
|
+
);
|
|
71
90
|
const messageType = 'customEvent';
|
|
72
91
|
const callback = vi.fn();
|
|
73
92
|
component.on(messageType, callback);
|
|
@@ -78,7 +97,10 @@ describe('EmbeddedComponent', () => {
|
|
|
78
97
|
});
|
|
79
98
|
|
|
80
99
|
test('off', () => {
|
|
81
|
-
const component = new EmbeddedComponent
|
|
100
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
101
|
+
url,
|
|
102
|
+
value,
|
|
103
|
+
);
|
|
82
104
|
const messageType = 'customEvent';
|
|
83
105
|
const callback = vi.fn();
|
|
84
106
|
component.on(messageType, callback);
|
|
@@ -96,7 +118,8 @@ describe('EmbeddedComponent', () => {
|
|
|
96
118
|
let messageHandler: (event: MessageEvent) => void;
|
|
97
119
|
let port: MessagePort;
|
|
98
120
|
let handshake: MessageEvent;
|
|
99
|
-
let component: EmbeddedComponent
|
|
121
|
+
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
122
|
+
let options: TransactionOptions;
|
|
100
123
|
|
|
101
124
|
beforeEach(() => {
|
|
102
125
|
port = {
|
|
@@ -113,7 +136,12 @@ describe('EmbeddedComponent', () => {
|
|
|
113
136
|
.mockImplementation((event, handler) => {
|
|
114
137
|
messageHandler = handler;
|
|
115
138
|
});
|
|
116
|
-
|
|
139
|
+
options = { allowedAgentTypes: [AgentType.PRIVATE, AgentType.VASP] };
|
|
140
|
+
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
141
|
+
url,
|
|
142
|
+
value,
|
|
143
|
+
options,
|
|
144
|
+
);
|
|
117
145
|
component.mount(parentId);
|
|
118
146
|
|
|
119
147
|
expect(messageHandler).toBeDefined();
|
|
@@ -121,40 +149,382 @@ describe('EmbeddedComponent', () => {
|
|
|
121
149
|
});
|
|
122
150
|
|
|
123
151
|
test('send', () => {
|
|
124
|
-
const message: HostMessage = {
|
|
152
|
+
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
125
153
|
type: HMType.UPDATE,
|
|
126
|
-
value: {
|
|
154
|
+
value: {
|
|
155
|
+
requestId: 'id',
|
|
156
|
+
},
|
|
157
|
+
options: { allowedAgentTypes: [AgentType.PRIVATE] },
|
|
127
158
|
};
|
|
128
159
|
component.send(message);
|
|
129
|
-
|
|
130
|
-
// Assert that the message is sent to the embedded component
|
|
131
|
-
// and handled correctly.
|
|
160
|
+
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
132
161
|
});
|
|
133
162
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
163
|
+
describe('update', () => {
|
|
164
|
+
test('with out options', () => {
|
|
165
|
+
const newValue: Partial<Transaction> = { amountDecimal: 200 };
|
|
137
166
|
|
|
138
|
-
|
|
139
|
-
|
|
167
|
+
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
168
|
+
type: HMType.UPDATE,
|
|
169
|
+
value: newValue,
|
|
170
|
+
options,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
component.update(newValue);
|
|
174
|
+
|
|
175
|
+
expect(component.value).toBe(newValue);
|
|
176
|
+
expect(component.options).toBe(options);
|
|
177
|
+
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test('with options', () => {
|
|
181
|
+
const newValue: Partial<Transaction> = { amountDecimal: 200 };
|
|
182
|
+
const newOptions = { allowedAgentTypes: [AgentType.PRIVATE] };
|
|
183
|
+
|
|
184
|
+
const message: HostMessage<Withdrawal, TransactionOptions> = {
|
|
185
|
+
type: HMType.UPDATE,
|
|
186
|
+
value: newValue,
|
|
187
|
+
options: newOptions,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
component.update(newValue, newOptions);
|
|
140
191
|
|
|
192
|
+
expect(component.value).toBe(newValue);
|
|
193
|
+
expect(component.options).toBe(newOptions);
|
|
194
|
+
expect(port.postMessage).toHaveBeenCalledWith(message);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
141
197
|
// TODO not sure this actually does what I want it to do
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
198
|
+
describe('completion', () => {
|
|
199
|
+
test('resolves with response and cleans up listeners', async () => {
|
|
200
|
+
const response = { valid: true, value: 'completed' };
|
|
201
|
+
const completionPromise = component.completion();
|
|
202
|
+
|
|
203
|
+
port.onmessage!({
|
|
204
|
+
data: { type: CMType.COMPLETE, response },
|
|
205
|
+
} as unknown as MessageEvent);
|
|
206
|
+
|
|
207
|
+
const result = await completionPromise;
|
|
208
|
+
expect(result).toBe(response);
|
|
145
209
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
} as MessageEvent);
|
|
210
|
+
// Verify cleanup by sending another complete message - should not trigger anything
|
|
211
|
+
port.onmessage!({
|
|
212
|
+
data: { type: CMType.COMPLETE, response: { valid: false } },
|
|
213
|
+
} as unknown as MessageEvent);
|
|
151
214
|
|
|
152
|
-
|
|
215
|
+
// Original result should remain unchanged
|
|
153
216
|
expect(result).toBe(response);
|
|
154
217
|
});
|
|
155
|
-
|
|
156
|
-
|
|
218
|
+
|
|
219
|
+
test('rejects with error and cleans up listeners', async () => {
|
|
220
|
+
const errorMessage = 'Test error';
|
|
221
|
+
const completionPromise = component.completion();
|
|
222
|
+
|
|
223
|
+
port.onmessage!({
|
|
224
|
+
data: { type: 'error', message: errorMessage },
|
|
225
|
+
} as unknown as MessageEvent);
|
|
226
|
+
|
|
227
|
+
await expect(completionPromise).rejects.toThrow(errorMessage);
|
|
228
|
+
|
|
229
|
+
// Verify cleanup by sending another error - should not trigger anything
|
|
230
|
+
port.onmessage!({
|
|
231
|
+
data: { type: 'error', message: 'Different error' },
|
|
232
|
+
} as unknown as MessageEvent);
|
|
233
|
+
|
|
234
|
+
// Original rejection should remain
|
|
235
|
+
await expect(completionPromise).rejects.toThrow(errorMessage);
|
|
236
|
+
});
|
|
157
237
|
});
|
|
158
238
|
});
|
|
159
239
|
});
|
|
240
|
+
|
|
241
|
+
describe('modal', () => {
|
|
242
|
+
let document: Document;
|
|
243
|
+
let dialog: HTMLDialogElement;
|
|
244
|
+
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
245
|
+
|
|
246
|
+
beforeEach(() => {
|
|
247
|
+
dialog = {
|
|
248
|
+
style: {},
|
|
249
|
+
showModal: vi.fn(),
|
|
250
|
+
close: vi.fn(),
|
|
251
|
+
remove: vi.fn(),
|
|
252
|
+
addEventListener: vi.fn(),
|
|
253
|
+
appendChild: vi.fn(), // Add this
|
|
254
|
+
} as unknown as HTMLDialogElement;
|
|
255
|
+
|
|
256
|
+
document = {
|
|
257
|
+
createElement: vi.fn().mockImplementation((tag) => {
|
|
258
|
+
if (tag === 'dialog') return dialog;
|
|
259
|
+
if (tag === 'iframe')
|
|
260
|
+
return {
|
|
261
|
+
style: {},
|
|
262
|
+
contentWindow: { focus: vi.fn() },
|
|
263
|
+
addEventListener: vi.fn(),
|
|
264
|
+
} as unknown as HTMLIFrameElement;
|
|
265
|
+
}),
|
|
266
|
+
body: {
|
|
267
|
+
appendChild: vi.fn(),
|
|
268
|
+
},
|
|
269
|
+
} as unknown as Document;
|
|
270
|
+
|
|
271
|
+
const mockDoc = document;
|
|
272
|
+
vi.stubGlobal('document', mockDoc); // Use intermediate variable
|
|
273
|
+
|
|
274
|
+
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
275
|
+
url,
|
|
276
|
+
value,
|
|
277
|
+
);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
afterEach(() => {
|
|
281
|
+
vi.unstubAllGlobals();
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test('modal closes on cancel message', () => {
|
|
285
|
+
component.openModal();
|
|
286
|
+
|
|
287
|
+
// Trigger cancel message through event manager
|
|
288
|
+
component['eventManager']['handleMessage']({
|
|
289
|
+
data: { type: CMType.CANCEL },
|
|
290
|
+
} as MessageEvent);
|
|
291
|
+
|
|
292
|
+
expect(dialog.close).toHaveBeenCalled();
|
|
293
|
+
expect(dialog.remove).toHaveBeenCalled();
|
|
294
|
+
// await expect(completionPromise).rejects.toThrow();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('modal closes on completion', async () => {
|
|
298
|
+
const completionPromise = component.openModal();
|
|
299
|
+
const response = { valid: true, value: 'completed' };
|
|
300
|
+
|
|
301
|
+
// Trigger complete message through event manager
|
|
302
|
+
component['eventManager']['handleMessage']({
|
|
303
|
+
data: { type: CMType.COMPLETE, response },
|
|
304
|
+
} as MessageEvent);
|
|
305
|
+
|
|
306
|
+
expect(dialog.close).toHaveBeenCalled();
|
|
307
|
+
expect(dialog.remove).toHaveBeenCalled();
|
|
308
|
+
await expect(completionPromise).resolves.toBe(response);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
describe('error handling', () => {
|
|
313
|
+
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
314
|
+
let mockMessageManager: (typeof component)['eventManager'];
|
|
315
|
+
let document: Document;
|
|
316
|
+
let parentElement: HTMLElement;
|
|
317
|
+
|
|
318
|
+
beforeEach(() => {
|
|
319
|
+
parentElement = {
|
|
320
|
+
appendChild: vi.fn(),
|
|
321
|
+
} as unknown as HTMLElement;
|
|
322
|
+
|
|
323
|
+
document = {
|
|
324
|
+
createElement: vi.fn().mockReturnValue({
|
|
325
|
+
style: {},
|
|
326
|
+
contentWindow: { focus: vi.fn() },
|
|
327
|
+
} as unknown as HTMLIFrameElement),
|
|
328
|
+
querySelector: vi.fn().mockReturnValue(parentElement),
|
|
329
|
+
} as unknown as Document;
|
|
330
|
+
|
|
331
|
+
const mockDoc = document;
|
|
332
|
+
vi.stubGlobal('document', mockDoc);
|
|
333
|
+
|
|
334
|
+
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
335
|
+
url,
|
|
336
|
+
value,
|
|
337
|
+
);
|
|
338
|
+
mockMessageManager = component['eventManager'];
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test('handles invalid messages', () => {
|
|
342
|
+
const errors = [{ attribute: 'test', message: 'error' }];
|
|
343
|
+
const newValue = { ...value, extra: 'data' };
|
|
344
|
+
|
|
345
|
+
mockMessageManager['handleMessage']({
|
|
346
|
+
data: {
|
|
347
|
+
type: CMType.INVALID,
|
|
348
|
+
errors,
|
|
349
|
+
value: newValue,
|
|
350
|
+
},
|
|
351
|
+
} as MessageEvent);
|
|
352
|
+
|
|
353
|
+
expect(component.errors).toEqual(errors);
|
|
354
|
+
expect(component.value).toEqual(newValue);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test('handles resize messages', () => {
|
|
358
|
+
const mockIframe = {
|
|
359
|
+
style: {},
|
|
360
|
+
contentWindow: { focus: vi.fn() },
|
|
361
|
+
} as unknown as HTMLIFrameElement;
|
|
362
|
+
|
|
363
|
+
document.createElement = vi.fn().mockReturnValue(mockIframe);
|
|
364
|
+
document.querySelector = vi.fn().mockReturnValue(parentElement);
|
|
365
|
+
|
|
366
|
+
component.mount(parentId);
|
|
367
|
+
|
|
368
|
+
mockMessageManager['handleMessage']({
|
|
369
|
+
data: {
|
|
370
|
+
type: CMType.RESIZE,
|
|
371
|
+
height: 500,
|
|
372
|
+
},
|
|
373
|
+
} as MessageEvent);
|
|
374
|
+
|
|
375
|
+
expect(mockIframe.style.height).toBe('500px');
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('event management', () => {
|
|
380
|
+
let component: EmbeddedComponent<Withdrawal, TransactionOptions>;
|
|
381
|
+
let mockWindow: Window;
|
|
382
|
+
beforeEach(() => {
|
|
383
|
+
// Create a mock window without modifying global
|
|
384
|
+
mockWindow = {
|
|
385
|
+
addEventListener: vi.fn(),
|
|
386
|
+
dispatchEvent: vi.fn(),
|
|
387
|
+
} as unknown as Window;
|
|
388
|
+
|
|
389
|
+
vi.stubGlobal('window', mockWindow);
|
|
390
|
+
|
|
391
|
+
component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
392
|
+
url,
|
|
393
|
+
value,
|
|
394
|
+
);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
afterEach(() => {
|
|
398
|
+
vi.unstubAllGlobals();
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
test('multiple listeners for same event type', () => {
|
|
402
|
+
const callback1 = vi.fn();
|
|
403
|
+
const callback2 = vi.fn();
|
|
404
|
+
|
|
405
|
+
component.on('test', callback1);
|
|
406
|
+
component.on('test', callback2);
|
|
407
|
+
|
|
408
|
+
// Trigger message via component's event manager
|
|
409
|
+
component['eventManager']['handleMessage']({
|
|
410
|
+
data: { type: 'test', payload: 'data' },
|
|
411
|
+
} as MessageEvent);
|
|
412
|
+
|
|
413
|
+
expect(callback1).toHaveBeenCalled();
|
|
414
|
+
expect(callback2).toHaveBeenCalled();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
test('removal of specific listener', () => {
|
|
418
|
+
const callback1 = vi.fn();
|
|
419
|
+
const callback2 = vi.fn();
|
|
420
|
+
|
|
421
|
+
component.on('test', callback1);
|
|
422
|
+
component.on('test', callback2);
|
|
423
|
+
component.off('test', callback1);
|
|
424
|
+
|
|
425
|
+
component['eventManager']['handleMessage']({
|
|
426
|
+
data: { type: 'test', payload: 'data' },
|
|
427
|
+
} as MessageEvent);
|
|
428
|
+
|
|
429
|
+
expect(callback1).not.toHaveBeenCalled();
|
|
430
|
+
expect(callback2).toHaveBeenCalled();
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe('cleanup', () => {
|
|
435
|
+
let mockIframe: HTMLIFrameElement;
|
|
436
|
+
let parentElement: HTMLElement;
|
|
437
|
+
let document: Document;
|
|
438
|
+
|
|
439
|
+
beforeEach(() => {
|
|
440
|
+
mockIframe = {
|
|
441
|
+
style: {},
|
|
442
|
+
src: '',
|
|
443
|
+
contentWindow: {
|
|
444
|
+
focus: vi.fn(),
|
|
445
|
+
} as unknown as Window,
|
|
446
|
+
remove: vi.fn(),
|
|
447
|
+
} as unknown as HTMLIFrameElement;
|
|
448
|
+
|
|
449
|
+
parentElement = {
|
|
450
|
+
appendChild: vi.fn(),
|
|
451
|
+
} as unknown as HTMLElement;
|
|
452
|
+
|
|
453
|
+
document = {
|
|
454
|
+
createElement: vi.fn().mockReturnValue(mockIframe),
|
|
455
|
+
querySelector: vi.fn().mockReturnValue(parentElement),
|
|
456
|
+
} as unknown as Document;
|
|
457
|
+
|
|
458
|
+
const mockDoc = document;
|
|
459
|
+
vi.stubGlobal('document', mockDoc);
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
afterEach(() => {
|
|
463
|
+
vi.unstubAllGlobals();
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test('removeEmbed cleans up iframe', () => {
|
|
467
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
468
|
+
url,
|
|
469
|
+
value,
|
|
470
|
+
);
|
|
471
|
+
component.mount(parentId);
|
|
472
|
+
|
|
473
|
+
component.removeEmbed();
|
|
474
|
+
expect(mockIframe.remove).toHaveBeenCalled();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test('cleanup on unmount', () => {
|
|
478
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
479
|
+
url,
|
|
480
|
+
value,
|
|
481
|
+
);
|
|
482
|
+
const callback = vi.fn();
|
|
483
|
+
component.on('test', callback);
|
|
484
|
+
|
|
485
|
+
component.mount(parentId);
|
|
486
|
+
|
|
487
|
+
component.removeEmbed();
|
|
488
|
+
|
|
489
|
+
// Create a new event manager to simulate cleanup
|
|
490
|
+
component['eventManager'] = new MessageEventManager();
|
|
491
|
+
|
|
492
|
+
// Try to trigger message after cleanup
|
|
493
|
+
component['eventManager']['handleMessage']({
|
|
494
|
+
data: { type: 'test', payload: 'data' },
|
|
495
|
+
} as MessageEvent);
|
|
496
|
+
|
|
497
|
+
expect(callback).not.toHaveBeenCalled();
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
describe('state management', () => {
|
|
502
|
+
test('maintains value and options state', () => {
|
|
503
|
+
const initialValue = { amountDecimal: 100 };
|
|
504
|
+
const initialOptions = { allowedAgentTypes: [AgentType.PRIVATE] };
|
|
505
|
+
|
|
506
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
507
|
+
url,
|
|
508
|
+
initialValue,
|
|
509
|
+
initialOptions,
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
expect(component.value).toEqual(initialValue);
|
|
513
|
+
expect(component.options).toEqual(initialOptions);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test('updates maintain state consistency', () => {
|
|
517
|
+
const component = new EmbeddedComponent<Withdrawal, TransactionOptions>(
|
|
518
|
+
url,
|
|
519
|
+
value,
|
|
520
|
+
);
|
|
521
|
+
const newValue = { amountDecimal: 200 };
|
|
522
|
+
const newOptions = { allowedAgentTypes: [AgentType.VASP] };
|
|
523
|
+
|
|
524
|
+
component.update(newValue, newOptions);
|
|
525
|
+
|
|
526
|
+
expect(component.value).toEqual(newValue);
|
|
527
|
+
expect(component.options).toEqual(newOptions);
|
|
528
|
+
});
|
|
529
|
+
});
|
|
160
530
|
});
|