scandit-datacapture-frameworks-id 8.4.1 → 8.5.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.
Files changed (39) hide show
  1. package/dist/dts/common/DateResult.d.ts +1 -1
  2. package/dist/dts/common/IdImages.d.ts +2 -2
  3. package/dist/dts/common/RegionSpecificSubtype.d.ts +3 -1
  4. package/dist/dts/defaults/IdDefaults.d.ts +5 -6
  5. package/dist/dts/defaults/getIdDefaults.d.ts +2 -0
  6. package/dist/dts/defaults/index.d.ts +1 -0
  7. package/dist/dts/defaults/loadDefaults.d.ts +1 -1
  8. package/dist/dts/id/AamvaBarcodeVerificationResult.d.ts +1 -1
  9. package/dist/dts/id/BarcodeResult.d.ts +4 -4
  10. package/dist/dts/id/DataConsistencyResult.d.ts +2 -2
  11. package/dist/dts/id/DrivingLicenseCategory.d.ts +2 -2
  12. package/dist/dts/id/DrivingLicenseDetails.d.ts +2 -2
  13. package/dist/dts/id/MRZResult.d.ts +2 -2
  14. package/dist/dts/id/MobileDocumentOCRResult.d.ts +1 -1
  15. package/dist/dts/id/MobileDocumentResult.d.ts +3 -3
  16. package/dist/dts/id/NfcResult.d.ts +4 -4
  17. package/dist/dts/id/ProfessionalDrivingPermit.d.ts +2 -2
  18. package/dist/dts/id/VehicleRestriction.d.ts +2 -2
  19. package/dist/dts/id/VerificationResult.d.ts +3 -3
  20. package/dist/dts/idcapture/IdCapture.d.ts +4 -4
  21. package/dist/dts/idcapture/IdCaptureFeedback.d.ts +2 -2
  22. package/dist/dts/iddocumenttype/DriverLicense.d.ts +4 -4
  23. package/dist/dts/iddocumenttype/HealthInsuranceCard.d.ts +4 -4
  24. package/dist/dts/iddocumenttype/IdCaptureDocument.d.ts +2 -2
  25. package/dist/dts/iddocumenttype/IdCard.d.ts +4 -4
  26. package/dist/dts/iddocumenttype/Passport.d.ts +4 -4
  27. package/dist/dts/iddocumenttype/RegionSpecific.d.ts +5 -5
  28. package/dist/dts/iddocumenttype/ResidencePermit.d.ts +4 -4
  29. package/dist/dts/iddocumenttype/VisaIcao.d.ts +4 -4
  30. package/dist/dts/proxy-types.d.ts +1 -1
  31. package/dist/dts/scanner/FullDocumentScanner.d.ts +2 -2
  32. package/dist/dts/scanner/IdCaptureScanner.d.ts +3 -3
  33. package/dist/dts/scanner/MobileDocumentScanner.d.ts +2 -2
  34. package/dist/dts/scanner/SingleSideScanner.d.ts +2 -2
  35. package/dist/index.js +253 -121
  36. package/dist/index.js.map +1 -1
  37. package/jest.config.js +27 -0
  38. package/package.json +2 -2
  39. package/test/IdCaptureListenerSubscription.test.ts +96 -0
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect, jest, beforeEach } from '@jest/globals';
2
+ import { IdCapture, PrivateIdCapture } from '../src/idcapture/IdCapture';
3
+ import { IdCaptureListener } from '../src/idcapture/IdCaptureListener';
4
+
5
+ /**
6
+ * Regression tests for SDC-32399.
7
+ *
8
+ * `IdCapture.addListener` must subscribe to native events when it adds the FIRST
9
+ * listener — regardless of whether the listener is added before or after the mode
10
+ * is wired into the DataCaptureContext via `setMode`.
11
+ *
12
+ * The original bug pushed the listener onto the array BEFORE checking
13
+ * `listeners.length === 0`, so the guard was never true and `subscribeListener`
14
+ * was never called from `addListener`. With the awaited "setMode-before-addListener"
15
+ * order the listener controller's `initialize()` also ran with zero listeners, so
16
+ * nothing ever subscribed and `didCaptureId`/`didRejectId` were silently dropped
17
+ * (reproduced on Android RN New Architecture).
18
+ *
19
+ * These tests bypass the constructor (which needs FactoryMaker proxy bindings) and
20
+ * exercise the real `addListener`/`removeListener` logic against a stubbed listener
21
+ * controller, which is exactly where the ordering bug lived.
22
+ */
23
+ describe('IdCapture listener subscription (SDC-32399)', () => {
24
+ let subscribeListener: jest.Mock<() => Promise<void>>;
25
+ let unsubscribeListener: jest.Mock<() => Promise<void>>;
26
+ let idCapture: PrivateIdCapture;
27
+
28
+ const makeListener = (): IdCaptureListener => ({
29
+ didCaptureId: jest.fn(),
30
+ didRejectId: jest.fn(),
31
+ });
32
+
33
+ beforeEach(() => {
34
+ subscribeListener = jest.fn(() => Promise.resolve());
35
+ unsubscribeListener = jest.fn(() => Promise.resolve());
36
+
37
+ // Bypass the constructor's FactoryMaker/proxy dependencies; we only need the
38
+ // listener bookkeeping fields that addListener/removeListener touch.
39
+ idCapture = Object.create(IdCapture.prototype) as PrivateIdCapture;
40
+ (idCapture as any).listeners = [];
41
+ (idCapture as any)._hasListeners = false;
42
+ // Simulates the controller created lazily when `_context` is set (i.e. setMode).
43
+ (idCapture as any).listenerController = { subscribeListener, unsubscribeListener };
44
+ });
45
+
46
+ it('subscribes when the first listener is added after the context is set (setMode → addListener)', async () => {
47
+ // given a context-attached mode with the controller already created but no listeners yet
48
+ // when the first listener is added
49
+ await (idCapture as any).addListener(makeListener());
50
+
51
+ // then native events must be subscribed exactly once
52
+ expect(subscribeListener).toHaveBeenCalledTimes(1);
53
+ expect((idCapture as any).listeners).toHaveLength(1);
54
+ });
55
+
56
+ it('subscribes only once when several listeners are added', async () => {
57
+ await (idCapture as any).addListener(makeListener());
58
+ await (idCapture as any).addListener(makeListener());
59
+ await (idCapture as any).addListener(makeListener());
60
+
61
+ expect(subscribeListener).toHaveBeenCalledTimes(1);
62
+ expect((idCapture as any).listeners).toHaveLength(3);
63
+ });
64
+
65
+ it('does not re-subscribe when the same listener is added twice', async () => {
66
+ const listener = makeListener();
67
+ await (idCapture as any).addListener(listener);
68
+ await (idCapture as any).addListener(listener);
69
+
70
+ expect(subscribeListener).toHaveBeenCalledTimes(1);
71
+ expect((idCapture as any).listeners).toHaveLength(1);
72
+ });
73
+
74
+ it('is a no-op subscribe when no controller exists yet (addListener → setMode)', async () => {
75
+ // given a listener added before the context exists (controller still null)
76
+ (idCapture as any).listenerController = null;
77
+
78
+ // when the first listener is added, the optional-chained subscribe is skipped...
79
+ await (idCapture as any).addListener(makeListener());
80
+
81
+ // ...and the listener is still tracked so the controller's initialize() can
82
+ // subscribe once the context is set.
83
+ expect((idCapture as any).listeners).toHaveLength(1);
84
+ expect((idCapture as any)._hasListeners).toBe(true);
85
+ });
86
+
87
+ it('unsubscribes when the last listener is removed', async () => {
88
+ const listener = makeListener();
89
+ await (idCapture as any).addListener(listener);
90
+ await (idCapture as any).removeListener(listener);
91
+
92
+ expect(unsubscribeListener).toHaveBeenCalledTimes(1);
93
+ expect((idCapture as any).listeners).toHaveLength(0);
94
+ expect((idCapture as any)._hasListeners).toBe(false);
95
+ });
96
+ });