@incodetech/core 2.0.0-alpha.2 → 2.0.0-alpha.4

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 (154) hide show
  1. package/dist/OpenViduLogger-BdPfiZO6.esm.js +3 -0
  2. package/dist/OpenViduLogger-CQyDxBvM.esm.js +803 -0
  3. package/dist/{addEvent-1Mi5CEiq.esm.js → addEvent-9v4w5iO-.esm.js} +1 -1
  4. package/dist/email.d.ts +1 -1
  5. package/dist/email.esm.js +2 -2
  6. package/dist/{endpoints-D_pUMaqA.esm.js → endpoints-Dn1t57hJ.esm.js} +8 -3
  7. package/dist/flow.d.ts +3 -3
  8. package/dist/flow.esm.js +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.esm.js +2 -2
  11. package/dist/{lib-CyIAFRfr.esm.js → lib-Bu9XGMBW.esm.js} +1 -800
  12. package/dist/{permissionServices-CVR0Pq38.esm.js → permissionServices-CCpxd8le.esm.js} +1 -1
  13. package/dist/phone.d.ts +1 -1
  14. package/dist/phone.esm.js +2 -2
  15. package/dist/selfie.d.ts +5 -4
  16. package/dist/selfie.esm.js +27 -10
  17. package/package.json +4 -1
  18. package/.turbo/turbo-build.log +0 -33
  19. package/.turbo/turbo-coverage.log +0 -22
  20. package/.turbo/turbo-format.log +0 -6
  21. package/.turbo/turbo-lint$colon$fix.log +0 -77
  22. package/.turbo/turbo-lint.log +0 -95
  23. package/.turbo/turbo-test.log +0 -870
  24. package/.turbo/turbo-typecheck.log +0 -5
  25. package/coverage/base.css +0 -224
  26. package/coverage/block-navigation.js +0 -87
  27. package/coverage/favicon.png +0 -0
  28. package/coverage/index.html +0 -221
  29. package/coverage/prettify.css +0 -1
  30. package/coverage/prettify.js +0 -2
  31. package/coverage/sort-arrow-sprite.png +0 -0
  32. package/coverage/sorter.js +0 -210
  33. package/coverage/src/camera/cameraService.ts.html +0 -580
  34. package/coverage/src/camera/cameraServices.ts.html +0 -163
  35. package/coverage/src/camera/cameraStateMachine.ts.html +0 -877
  36. package/coverage/src/camera/index.html +0 -146
  37. package/coverage/src/email/emailActor.ts.html +0 -130
  38. package/coverage/src/email/emailManager.ts.html +0 -1366
  39. package/coverage/src/email/emailStateMachine.ts.html +0 -1186
  40. package/coverage/src/email/index.html +0 -146
  41. package/coverage/src/flow/flowActor.ts.html +0 -124
  42. package/coverage/src/flow/flowAnalyzer.ts.html +0 -196
  43. package/coverage/src/flow/flowManager.ts.html +0 -790
  44. package/coverage/src/flow/flowServices.ts.html +0 -124
  45. package/coverage/src/flow/flowStateMachine.ts.html +0 -631
  46. package/coverage/src/flow/index.html +0 -221
  47. package/coverage/src/flow/moduleLoader.ts.html +0 -304
  48. package/coverage/src/flow/orchestratedFlowManager.ts.html +0 -778
  49. package/coverage/src/flow/orchestratedFlowStateMachine.ts.html +0 -1060
  50. package/coverage/src/http/api.ts.html +0 -355
  51. package/coverage/src/http/endpoints.ts.html +0 -136
  52. package/coverage/src/http/index.html +0 -131
  53. package/coverage/src/index.html +0 -116
  54. package/coverage/src/phone/index.html +0 -146
  55. package/coverage/src/phone/phoneActor.ts.html +0 -130
  56. package/coverage/src/phone/phoneManager.ts.html +0 -1459
  57. package/coverage/src/phone/phoneStateMachine.ts.html +0 -1351
  58. package/coverage/src/recordings/index.html +0 -116
  59. package/coverage/src/recordings/recordingsRepository.ts.html +0 -229
  60. package/coverage/src/selfie/index.html +0 -191
  61. package/coverage/src/selfie/selfieActor.ts.html +0 -136
  62. package/coverage/src/selfie/selfieErrorUtils.ts.html +0 -283
  63. package/coverage/src/selfie/selfieManager.ts.html +0 -988
  64. package/coverage/src/selfie/selfieStateMachine.ts.html +0 -2497
  65. package/coverage/src/selfie/selfieUploadService.ts.html +0 -328
  66. package/coverage/src/selfie/types.ts.html +0 -394
  67. package/coverage/src/setup.ts.html +0 -598
  68. package/src/camera/cameraActor.ts +0 -21
  69. package/src/camera/cameraService.test.ts +0 -437
  70. package/src/camera/cameraService.ts +0 -165
  71. package/src/camera/cameraServices.test.ts +0 -66
  72. package/src/camera/cameraServices.ts +0 -26
  73. package/src/camera/cameraStateMachine.test.ts +0 -602
  74. package/src/camera/cameraStateMachine.ts +0 -264
  75. package/src/camera/index.ts +0 -5
  76. package/src/camera/types.ts +0 -17
  77. package/src/device/getBrowser.ts +0 -31
  78. package/src/device/getDeviceClass.ts +0 -29
  79. package/src/device/index.ts +0 -2
  80. package/src/email/__mocks__/emailMocks.ts +0 -59
  81. package/src/email/emailActor.ts +0 -15
  82. package/src/email/emailManager.test.ts +0 -573
  83. package/src/email/emailManager.ts +0 -427
  84. package/src/email/emailServices.ts +0 -66
  85. package/src/email/emailStateMachine.test.ts +0 -741
  86. package/src/email/emailStateMachine.ts +0 -367
  87. package/src/email/index.ts +0 -39
  88. package/src/email/types.ts +0 -60
  89. package/src/events/addEvent.ts +0 -20
  90. package/src/events/types.ts +0 -7
  91. package/src/flow/__mocks__/flowMocks.ts +0 -84
  92. package/src/flow/flowActor.ts +0 -13
  93. package/src/flow/flowAnalyzer.test.ts +0 -266
  94. package/src/flow/flowAnalyzer.ts +0 -37
  95. package/src/flow/flowCompletionService.ts +0 -21
  96. package/src/flow/flowManager.test.ts +0 -560
  97. package/src/flow/flowManager.ts +0 -235
  98. package/src/flow/flowServices.test.ts +0 -109
  99. package/src/flow/flowServices.ts +0 -13
  100. package/src/flow/flowStateMachine.test.ts +0 -334
  101. package/src/flow/flowStateMachine.ts +0 -182
  102. package/src/flow/index.ts +0 -21
  103. package/src/flow/moduleLoader.test.ts +0 -136
  104. package/src/flow/moduleLoader.ts +0 -73
  105. package/src/flow/orchestratedFlowManager.test.ts +0 -240
  106. package/src/flow/orchestratedFlowManager.ts +0 -231
  107. package/src/flow/orchestratedFlowStateMachine.test.ts +0 -199
  108. package/src/flow/orchestratedFlowStateMachine.ts +0 -325
  109. package/src/flow/types.ts +0 -434
  110. package/src/http/__mocks__/api.ts +0 -88
  111. package/src/http/api.test.ts +0 -231
  112. package/src/http/api.ts +0 -90
  113. package/src/http/endpoints.ts +0 -17
  114. package/src/index.ts +0 -33
  115. package/src/permissions/index.ts +0 -2
  116. package/src/permissions/permissionServices.ts +0 -31
  117. package/src/permissions/types.ts +0 -3
  118. package/src/phone/__mocks__/phoneMocks.ts +0 -71
  119. package/src/phone/index.ts +0 -39
  120. package/src/phone/phoneActor.ts +0 -15
  121. package/src/phone/phoneManager.test.ts +0 -393
  122. package/src/phone/phoneManager.ts +0 -458
  123. package/src/phone/phoneServices.ts +0 -98
  124. package/src/phone/phoneStateMachine.test.ts +0 -918
  125. package/src/phone/phoneStateMachine.ts +0 -422
  126. package/src/phone/types.ts +0 -83
  127. package/src/recordings/recordingsRepository.test.ts +0 -87
  128. package/src/recordings/recordingsRepository.ts +0 -48
  129. package/src/recordings/streamingEvents.ts +0 -10
  130. package/src/selfie/__mocks__/selfieMocks.ts +0 -26
  131. package/src/selfie/index.ts +0 -14
  132. package/src/selfie/selfieActor.ts +0 -17
  133. package/src/selfie/selfieErrorUtils.test.ts +0 -116
  134. package/src/selfie/selfieErrorUtils.ts +0 -66
  135. package/src/selfie/selfieManager.test.ts +0 -297
  136. package/src/selfie/selfieManager.ts +0 -301
  137. package/src/selfie/selfieServices.ts +0 -362
  138. package/src/selfie/selfieStateMachine.test.ts +0 -283
  139. package/src/selfie/selfieStateMachine.ts +0 -804
  140. package/src/selfie/selfieUploadService.test.ts +0 -90
  141. package/src/selfie/selfieUploadService.ts +0 -81
  142. package/src/selfie/types.ts +0 -103
  143. package/src/session/index.ts +0 -5
  144. package/src/session/sessionService.ts +0 -78
  145. package/src/setup.test.ts +0 -61
  146. package/src/setup.ts +0 -171
  147. package/tsconfig.json +0 -13
  148. package/tsdown.config.ts +0 -22
  149. package/vitest.config.ts +0 -37
  150. package/vitest.setup.ts +0 -135
  151. /package/dist/{Manager-6BwbaI_H.d.ts → Manager-BGfxEmyv.d.ts} +0 -0
  152. /package/dist/{StateMachine-7c1gcu94.d.ts → StateMachine-DRE1oH2B.d.ts} +0 -0
  153. /package/dist/{types-tq1ypYSL.d.ts → types-kWlqshfM.d.ts} +0 -0
  154. /package/dist/{warmup-Dr7OcFND.d.ts → warmup-CEJTfxQr.d.ts} +0 -0
@@ -1,602 +0,0 @@
1
- import { createActor, MockCameraProvider } from '@incodetech/infra';
2
- import { beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { cameraMachine } from './cameraStateMachine';
4
-
5
- const createTestActor = () => {
6
- const camera = new MockCameraProvider();
7
- return createActor(cameraMachine, {
8
- input: { camera },
9
- }).start();
10
- };
11
-
12
- // Helper to mock permission query result
13
- const mockPermissionQuery = (state: 'granted' | 'denied' | 'prompt') => {
14
- const setPermissionState = (
15
- globalThis as {
16
- __setPermissionState?: (state: 'granted' | 'denied' | 'prompt') => void;
17
- }
18
- ).__setPermissionState;
19
- if (setPermissionState) {
20
- setPermissionState(state);
21
- }
22
- };
23
-
24
- describe('CameraStateMachine', () => {
25
- describe('Initial state', () => {
26
- it('should start in idle state', () => {
27
- const actor = createTestActor();
28
-
29
- expect(actor.getSnapshot().value).toBe('idle');
30
- actor.stop();
31
- });
32
-
33
- it('should have initial context with camera capability', () => {
34
- const actor = createTestActor();
35
-
36
- const { context } = actor.getSnapshot();
37
- expect(context.camera).toBeDefined();
38
- expect(context.stream).toBeUndefined();
39
- expect(context.permissionResult).toBeUndefined();
40
- expect(context.error).toBeUndefined();
41
- expect(context.errorType).toBeUndefined();
42
-
43
- actor.stop();
44
- });
45
- });
46
-
47
- describe('START event', () => {
48
- it('should transition from idle to checkingPermission', () => {
49
- const actor = createTestActor();
50
-
51
- actor.send({ type: 'START' });
52
-
53
- expect(actor.getSnapshot().value).toBe('checkingPermission');
54
- actor.stop();
55
- });
56
- });
57
-
58
- describe('Permission checking flow', () => {
59
- it('should transition to routing after permission check', async () => {
60
- const actor = createTestActor();
61
-
62
- actor.send({ type: 'START' });
63
-
64
- await vi.waitFor(
65
- () => {
66
- const snapshot = actor.getSnapshot();
67
- expect(['routing', 'requesting', 'streaming']).toContain(
68
- snapshot.value,
69
- );
70
- },
71
- { timeout: 2000 },
72
- );
73
-
74
- actor.stop();
75
- });
76
-
77
- it('should set permission result in context', async () => {
78
- const actor = createTestActor();
79
-
80
- actor.send({ type: 'START' });
81
-
82
- await vi.waitFor(
83
- () => {
84
- const snapshot = actor.getSnapshot();
85
- if (
86
- snapshot.value === 'routing' ||
87
- snapshot.value === 'requesting' ||
88
- snapshot.value === 'streaming'
89
- ) {
90
- expect(snapshot.context.permissionResult).toBeDefined();
91
- }
92
- },
93
- { timeout: 2000 },
94
- );
95
-
96
- actor.stop();
97
- });
98
- });
99
-
100
- describe('Stream request flow', () => {
101
- it('should transition to streaming on successful stream', async () => {
102
- const camera = new MockCameraProvider();
103
- const mockStream = new MediaStream();
104
- camera.setMockStream(mockStream);
105
- const actor = createActor(cameraMachine, {
106
- input: { camera },
107
- }).start();
108
-
109
- actor.send({ type: 'START' });
110
-
111
- await vi.waitFor(
112
- () => {
113
- const value = actor.getSnapshot().value;
114
- if (value !== 'streaming' && value !== 'error') {
115
- throw new Error(`Still in state: ${value}`);
116
- }
117
- },
118
- { timeout: 5000, interval: 50 },
119
- );
120
-
121
- const snapshot = actor.getSnapshot();
122
- expect(snapshot.value).toBe('streaming');
123
- expect(snapshot.context.stream).toBe(mockStream);
124
-
125
- actor.stop();
126
- });
127
-
128
- it('should transition to error on stream failure', async () => {
129
- const camera = new MockCameraProvider();
130
- camera.setShouldReject(true);
131
- const actor = createActor(cameraMachine, {
132
- input: { camera },
133
- }).start();
134
-
135
- actor.send({ type: 'START' });
136
-
137
- await vi.waitFor(
138
- () => {
139
- const value = actor.getSnapshot().value;
140
- if (value !== 'error' && value !== 'streaming') {
141
- throw new Error(`Still in state: ${value}`);
142
- }
143
- },
144
- { timeout: 5000, interval: 50 },
145
- );
146
-
147
- const snapshot = actor.getSnapshot();
148
- expect(snapshot.value).toBe('error');
149
- expect(snapshot.context.error).toBeDefined();
150
- expect(snapshot.context.errorType).toBeDefined();
151
-
152
- actor.stop();
153
- });
154
- });
155
-
156
- describe('STOP event', () => {
157
- it('should transition from checkingPermission to idle', () => {
158
- const actor = createTestActor();
159
-
160
- actor.send({ type: 'START' });
161
- actor.send({ type: 'STOP' });
162
-
163
- expect(actor.getSnapshot().value).toBe('idle');
164
- actor.stop();
165
- });
166
-
167
- it('should transition from requesting to idle', () => {
168
- const actor = createTestActor();
169
-
170
- actor.send({ type: 'START' });
171
- actor.send({ type: 'STOP' });
172
-
173
- expect(actor.getSnapshot().value).toBe('idle');
174
- actor.stop();
175
- });
176
- });
177
-
178
- describe('Routing state', () => {
179
- beforeEach(() => {
180
- // Reset permission mock to default
181
- mockPermissionQuery('prompt');
182
- });
183
-
184
- it('should route to requesting when permission is granted', async () => {
185
- // Set mock BEFORE creating actor
186
- mockPermissionQuery('granted');
187
- const camera = new MockCameraProvider();
188
- const mockStream = new MediaStream();
189
- camera.setMockStream(mockStream);
190
- const actor = createActor(cameraMachine, {
191
- input: { camera },
192
- }).start();
193
-
194
- actor.send({ type: 'START' });
195
-
196
- // Wait for streaming state (granted -> routing -> requesting -> streaming)
197
- await vi.waitFor(
198
- () => {
199
- const value = actor.getSnapshot().value;
200
- if (value !== 'streaming' && value !== 'error') {
201
- throw new Error(`Still in state: ${value}`);
202
- }
203
- },
204
- { timeout: 5000, interval: 50 },
205
- );
206
-
207
- expect(actor.getSnapshot().value).toBe('streaming');
208
- expect(actor.getSnapshot().context.permissionResult).toBe('granted');
209
-
210
- actor.stop();
211
- });
212
-
213
- it('should route to error when permission is denied', async () => {
214
- // Set mock BEFORE creating actor
215
- mockPermissionQuery('denied');
216
- const camera = new MockCameraProvider();
217
- const actor = createActor(cameraMachine, {
218
- input: { camera },
219
- }).start();
220
-
221
- actor.send({ type: 'START' });
222
-
223
- // Wait for error state (denied -> routing -> error)
224
- await vi.waitFor(
225
- () => {
226
- const value = actor.getSnapshot().value;
227
- if (value !== 'error' && value !== 'streaming') {
228
- throw new Error(`Still in state: ${value}`);
229
- }
230
- },
231
- { timeout: 5000, interval: 50 },
232
- );
233
-
234
- const snapshot = actor.getSnapshot();
235
- expect(snapshot.value).toBe('error');
236
- expect(snapshot.context.permissionResult).toBe('denied');
237
- expect(snapshot.context.errorType).toBe('permission_denied');
238
-
239
- actor.stop();
240
- });
241
-
242
- it('should route to requesting when permission is prompt', async () => {
243
- // Set mock BEFORE creating actor
244
- mockPermissionQuery('prompt');
245
- const camera = new MockCameraProvider();
246
- const mockStream = new MediaStream();
247
- camera.setMockStream(mockStream);
248
- const actor = createActor(cameraMachine, {
249
- input: { camera },
250
- }).start();
251
-
252
- actor.send({ type: 'START' });
253
-
254
- // Wait for streaming (prompt -> routing -> requesting -> streaming)
255
- await vi.waitFor(
256
- () => {
257
- const value = actor.getSnapshot().value;
258
- if (value !== 'streaming' && value !== 'error') {
259
- throw new Error(`Still in state: ${value}`);
260
- }
261
- },
262
- { timeout: 5000, interval: 50 },
263
- );
264
-
265
- expect(actor.getSnapshot().value).toBe('streaming');
266
- expect(actor.getSnapshot().context.permissionResult).toBe('prompt');
267
-
268
- actor.stop();
269
- });
270
- });
271
-
272
- describe('Streaming state', () => {
273
- it('should transition to idle when STOP is sent from streaming', async () => {
274
- const camera = new MockCameraProvider();
275
- const mockStream = new MediaStream();
276
- camera.setMockStream(mockStream);
277
- const stopSpy = vi.spyOn(camera, 'stopStream');
278
- const actor = createActor(cameraMachine, {
279
- input: { camera },
280
- }).start();
281
-
282
- actor.send({ type: 'START' });
283
-
284
- // Wait for streaming state
285
- await vi.waitFor(
286
- () => {
287
- const snapshot = actor.getSnapshot();
288
- if (snapshot.value !== 'streaming' || !snapshot.context.stream) {
289
- throw new Error(`Not streaming yet: ${snapshot.value}`);
290
- }
291
- },
292
- { timeout: 5000, interval: 50 },
293
- );
294
-
295
- // Send STOP
296
- actor.send({ type: 'STOP' });
297
-
298
- // STOP should transition immediately (synchronous)
299
- const stopSnapshot = actor.getSnapshot();
300
- expect(stopSnapshot.value).toBe('idle');
301
-
302
- // stopStream should be called because stream was in context
303
- expect(stopSpy).toHaveBeenCalled();
304
-
305
- actor.stop();
306
- });
307
- });
308
-
309
- describe('Error state', () => {
310
- it('should transition to idle when RESET is sent from error', () => {
311
- const actor = createTestActor();
312
-
313
- // Manually transition to error state
314
- actor.send({ type: 'START' });
315
- actor.send({
316
- type: 'STREAM_ERROR',
317
- error: 'Test error',
318
- errorType: 'unknown',
319
- });
320
-
321
- // Wait a tick for state update
322
- const errorSnapshot = actor.getSnapshot();
323
- if (errorSnapshot.value === 'error') {
324
- actor.send({ type: 'RESET' });
325
- expect(actor.getSnapshot().value).toBe('idle');
326
- expect(actor.getSnapshot().context.error).toBeUndefined();
327
- expect(actor.getSnapshot().context.errorType).toBeUndefined();
328
- }
329
-
330
- actor.stop();
331
- });
332
-
333
- it('should transition to idle when STOP is sent from error', () => {
334
- const actor = createTestActor();
335
-
336
- // Manually transition to error state
337
- actor.send({ type: 'START' });
338
- actor.send({
339
- type: 'STREAM_ERROR',
340
- error: 'Test error',
341
- errorType: 'unknown',
342
- });
343
-
344
- // Wait a tick for state update
345
- const errorSnapshot = actor.getSnapshot();
346
- if (errorSnapshot.value === 'error') {
347
- actor.send({ type: 'STOP' });
348
- expect(actor.getSnapshot().value).toBe('idle');
349
- }
350
-
351
- actor.stop();
352
- });
353
- });
354
-
355
- describe('Error handling', () => {
356
- it('should set error type for NotAllowedError', async () => {
357
- const camera = new MockCameraProvider();
358
- camera.setShouldReject(
359
- true,
360
- new DOMException('Permission denied', 'NotAllowedError'),
361
- );
362
- const actor = createActor(cameraMachine, {
363
- input: { camera },
364
- }).start();
365
-
366
- actor.send({ type: 'START' });
367
-
368
- await vi.waitFor(
369
- () => {
370
- if (actor.getSnapshot().value !== 'error') {
371
- throw new Error('Not in error state yet');
372
- }
373
- },
374
- { timeout: 5000, interval: 50 },
375
- );
376
-
377
- const errorSnapshot = actor.getSnapshot();
378
- expect(errorSnapshot.value).toBe('error');
379
- expect(errorSnapshot.context.errorType).toBe('permission_denied');
380
-
381
- actor.stop();
382
- });
383
-
384
- it('should set error type for NotFoundError', async () => {
385
- const camera = new MockCameraProvider();
386
- camera.setShouldReject(
387
- true,
388
- new DOMException('Camera not found', 'NotFoundError'),
389
- );
390
- const actor = createActor(cameraMachine, {
391
- input: { camera },
392
- }).start();
393
-
394
- actor.send({ type: 'START' });
395
-
396
- await vi.waitFor(
397
- () => {
398
- if (actor.getSnapshot().value !== 'error') {
399
- throw new Error('Not in error state yet');
400
- }
401
- },
402
- { timeout: 5000, interval: 50 },
403
- );
404
-
405
- const errorSnapshot = actor.getSnapshot();
406
- expect(errorSnapshot.value).toBe('error');
407
- expect(errorSnapshot.context.errorType).toBe('not_found');
408
-
409
- actor.stop();
410
- });
411
-
412
- it('should set error type for NotReadableError', async () => {
413
- const camera = new MockCameraProvider();
414
- camera.setShouldReject(
415
- true,
416
- new DOMException('Camera in use', 'NotReadableError'),
417
- );
418
- const actor = createActor(cameraMachine, {
419
- input: { camera },
420
- }).start();
421
-
422
- actor.send({ type: 'START' });
423
-
424
- await vi.waitFor(
425
- () => {
426
- if (actor.getSnapshot().value !== 'error') {
427
- throw new Error('Not in error state yet');
428
- }
429
- },
430
- { timeout: 5000, interval: 50 },
431
- );
432
-
433
- const errorSnapshot = actor.getSnapshot();
434
- expect(errorSnapshot.value).toBe('error');
435
- expect(errorSnapshot.context.errorType).toBe('not_readable');
436
-
437
- actor.stop();
438
- });
439
-
440
- it('should set error type for OverconstrainedError', async () => {
441
- const camera = new MockCameraProvider();
442
- camera.setShouldReject(
443
- true,
444
- new DOMException('Constraints not supported', 'OverconstrainedError'),
445
- );
446
- const actor = createActor(cameraMachine, {
447
- input: { camera },
448
- }).start();
449
-
450
- actor.send({ type: 'START' });
451
-
452
- await vi.waitFor(
453
- () => {
454
- if (actor.getSnapshot().value !== 'error') {
455
- throw new Error('Not in error state yet');
456
- }
457
- },
458
- { timeout: 5000, interval: 50 },
459
- );
460
-
461
- const errorSnapshot = actor.getSnapshot();
462
- expect(errorSnapshot.value).toBe('error');
463
- expect(errorSnapshot.context.errorType).toBe('overconstrained');
464
-
465
- actor.stop();
466
- });
467
-
468
- it('should set error type for SecurityError', async () => {
469
- const camera = new MockCameraProvider();
470
- camera.setShouldReject(
471
- true,
472
- new DOMException('Security error', 'SecurityError'),
473
- );
474
- const actor = createActor(cameraMachine, {
475
- input: { camera },
476
- }).start();
477
-
478
- actor.send({ type: 'START' });
479
-
480
- await vi.waitFor(
481
- () => {
482
- if (actor.getSnapshot().value !== 'error') {
483
- throw new Error('Not in error state yet');
484
- }
485
- },
486
- { timeout: 5000, interval: 50 },
487
- );
488
-
489
- const errorSnapshot = actor.getSnapshot();
490
- expect(errorSnapshot.value).toBe('error');
491
- expect(errorSnapshot.context.errorType).toBe('security');
492
-
493
- actor.stop();
494
- });
495
-
496
- it('should set error type for AbortError', async () => {
497
- const camera = new MockCameraProvider();
498
- camera.setShouldReject(
499
- true,
500
- new DOMException('Request aborted', 'AbortError'),
501
- );
502
- const actor = createActor(cameraMachine, {
503
- input: { camera },
504
- }).start();
505
-
506
- actor.send({ type: 'START' });
507
-
508
- await vi.waitFor(
509
- () => {
510
- if (actor.getSnapshot().value !== 'error') {
511
- throw new Error('Not in error state yet');
512
- }
513
- },
514
- { timeout: 5000, interval: 50 },
515
- );
516
-
517
- const errorSnapshot = actor.getSnapshot();
518
- expect(errorSnapshot.value).toBe('error');
519
- expect(errorSnapshot.context.errorType).toBe('abort');
520
-
521
- actor.stop();
522
- });
523
-
524
- it('should set error type to unknown for unrecognized errors', async () => {
525
- const camera = new MockCameraProvider();
526
- camera.setShouldReject(true, new Error('Unknown error'));
527
- const actor = createActor(cameraMachine, {
528
- input: { camera },
529
- }).start();
530
-
531
- actor.send({ type: 'START' });
532
-
533
- await vi.waitFor(
534
- () => {
535
- if (actor.getSnapshot().value !== 'error') {
536
- throw new Error('Not in error state yet');
537
- }
538
- },
539
- { timeout: 5000, interval: 50 },
540
- );
541
-
542
- const errorSnapshot = actor.getSnapshot();
543
- expect(errorSnapshot.value).toBe('error');
544
- expect(errorSnapshot.context.errorType).toBe('unknown');
545
- expect(errorSnapshot.context.error).toBe('Unknown error');
546
-
547
- actor.stop();
548
- });
549
-
550
- it('should handle error without message', async () => {
551
- const camera = new MockCameraProvider();
552
- const errorWithoutMessage = new Error();
553
- errorWithoutMessage.message = '';
554
- camera.setShouldReject(true, errorWithoutMessage);
555
- const actor = createActor(cameraMachine, {
556
- input: { camera },
557
- }).start();
558
-
559
- actor.send({ type: 'START' });
560
-
561
- await vi.waitFor(
562
- () => {
563
- if (actor.getSnapshot().value !== 'error') {
564
- throw new Error('Not in error state yet');
565
- }
566
- },
567
- { timeout: 5000, interval: 50 },
568
- );
569
-
570
- const errorSnapshot = actor.getSnapshot();
571
- expect(errorSnapshot.value).toBe('error');
572
- expect(errorSnapshot.context.error).toBeDefined();
573
- expect(errorSnapshot.context.errorType).toBe('unknown');
574
-
575
- actor.stop();
576
- });
577
- });
578
-
579
- describe('Permission check error handling', () => {
580
- it('should handle permission check failure gracefully', async () => {
581
- const actor = createTestActor();
582
-
583
- actor.send({ type: 'START' });
584
-
585
- // Wait for permission check to complete (even if it fails)
586
- await vi.waitFor(
587
- () => {
588
- const snapshot = actor.getSnapshot();
589
- // Should transition to routing even on error (with prompt as default)
590
- return (
591
- snapshot.value === 'routing' ||
592
- snapshot.value === 'requesting' ||
593
- snapshot.value === 'streaming'
594
- );
595
- },
596
- { timeout: 2000 },
597
- );
598
-
599
- actor.stop();
600
- });
601
- });
602
- });