@webex/contact-center 3.12.0-next.95 → 3.12.0-next.97

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 (34) hide show
  1. package/dist/services/task/TaskUtils.js +51 -3
  2. package/dist/services/task/TaskUtils.js.map +1 -1
  3. package/dist/services/task/state-machine/TaskStateMachine.js +50 -14
  4. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
  5. package/dist/services/task/state-machine/actions.js +57 -33
  6. package/dist/services/task/state-machine/actions.js.map +1 -1
  7. package/dist/services/task/state-machine/guards.js +42 -0
  8. package/dist/services/task/state-machine/guards.js.map +1 -1
  9. package/dist/services/task/state-machine/types.js.map +1 -1
  10. package/dist/services/task/state-machine/uiControlsComputer.js +78 -28
  11. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
  12. package/dist/services/task/voice/Voice.js +5 -3
  13. package/dist/services/task/voice/Voice.js.map +1 -1
  14. package/dist/types/services/task/TaskUtils.d.ts +2 -0
  15. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +72 -22
  16. package/dist/types/services/task/state-machine/guards.d.ts +12 -0
  17. package/dist/types/services/task/state-machine/types.d.ts +2 -0
  18. package/dist/webex.js +1 -1
  19. package/package.json +2 -2
  20. package/src/services/task/TaskUtils.ts +100 -2
  21. package/src/services/task/state-machine/TaskStateMachine.ts +101 -12
  22. package/src/services/task/state-machine/actions.ts +88 -35
  23. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +73 -11
  24. package/src/services/task/state-machine/guards.ts +39 -0
  25. package/src/services/task/state-machine/types.ts +2 -0
  26. package/src/services/task/state-machine/uiControlsComputer.ts +135 -41
  27. package/src/services/task/voice/Voice.ts +6 -3
  28. package/test/unit/spec/services/task/TaskUtils.ts +29 -0
  29. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +826 -0
  30. package/test/unit/spec/services/task/state-machine/guards.ts +158 -0
  31. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +648 -5
  32. package/test/unit/spec/services/task/voice/Voice.ts +18 -0
  33. package/umd/contact-center.min.js +2 -2
  34. package/umd/contact-center.min.js.map +1 -1
@@ -65,6 +65,7 @@ describe('State Machine Guards', () => {
65
65
  consultCallHeld: false,
66
66
  consultInitiator: false,
67
67
  exitingConference: false,
68
+ hideBlindTransferForEpDnPendingMerge: false,
68
69
  consultDestinationType: null,
69
70
  taskData: createTaskData(),
70
71
  uiControlConfig: {agentId: 'agent-123'},
@@ -326,6 +327,163 @@ describe('State Machine Guards', () => {
326
327
  });
327
328
  });
328
329
 
330
+ describe('isPassiveConferenceTransferObserver', () => {
331
+ it('returns false when transfer was initiated via widgets', () => {
332
+ const ctx = createContext({transferConferenceRequested: true, consultInitiator: false});
333
+ expect(
334
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData()))
335
+ ).toBe(false);
336
+ });
337
+
338
+ it('returns false when this agent initiated the consult transfer', () => {
339
+ const ctx = createContext({transferConferenceRequested: false, consultInitiator: false});
340
+ const taskData = createTaskData({consultingAgentId: 'agent-123'});
341
+ expect(
342
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData(taskData)))
343
+ ).toBe(false);
344
+ });
345
+
346
+ it('returns true when only stale consultInitiator is set without consultingAgentId evidence', () => {
347
+ const ctx = createContext({transferConferenceRequested: false, consultInitiator: true});
348
+ expect(
349
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData()))
350
+ ).toBe(true);
351
+ });
352
+
353
+ it('returns false when self is absent from participants snapshot', () => {
354
+ const ctx = createContext({consultInitiator: false});
355
+ const taskData = createTaskData({
356
+ interaction: {
357
+ ...createTaskData().interaction,
358
+ participants: {
359
+ 'other-agent': createParticipant('other-agent', 'Agent'),
360
+ },
361
+ },
362
+ });
363
+ expect(
364
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData(taskData)))
365
+ ).toBe(false);
366
+ });
367
+
368
+ it('returns false when self hasLeft in participants snapshot', () => {
369
+ const ctx = createContext({consultInitiator: false});
370
+ const taskData = createTaskData({
371
+ interaction: {
372
+ ...createTaskData().interaction,
373
+ participants: {
374
+ 'agent-123': createParticipant('agent-123', 'Agent', true),
375
+ },
376
+ },
377
+ });
378
+ expect(
379
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData(taskData)))
380
+ ).toBe(false);
381
+ });
382
+
383
+ it('returns true for passive observer still in the conference', () => {
384
+ const ctx = createContext({transferConferenceRequested: false, consultInitiator: false});
385
+ const taskData = createTaskData({
386
+ interaction: {
387
+ ...createTaskData().interaction,
388
+ participants: {
389
+ 'agent-123': createParticipant('agent-123', 'Agent'),
390
+ 'other-agent': createParticipant('other-agent', 'Agent'),
391
+ },
392
+ },
393
+ });
394
+ expect(
395
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData(taskData)))
396
+ ).toBe(true);
397
+ });
398
+
399
+ it('returns false when secondary agent initiated transfer via payload consultingAgentId', () => {
400
+ const ctx = createContext({transferConferenceRequested: false, consultInitiator: false});
401
+ const taskData = createTaskData({
402
+ isConsulted: true,
403
+ consultingAgentId: 'agent-123',
404
+ interaction: {
405
+ ...createTaskData().interaction,
406
+ participants: {
407
+ 'agent-123': {...createParticipant('agent-123', 'Agent'), consultState: 'consulting'},
408
+ },
409
+ media: {
410
+ ...createTaskData().interaction!.media,
411
+ 'consult-media': {
412
+ mediaResourceId: 'consult-media',
413
+ mediaType: 'telephony',
414
+ mediaMgr: 'media-mgr',
415
+ participants: ['agent-123', 'agent-456'],
416
+ mType: 'consult',
417
+ isHold: false,
418
+ holdTimestamp: null,
419
+ },
420
+ },
421
+ },
422
+ });
423
+ expect(
424
+ guards.isPassiveConferenceTransferObserver(createParams(ctx, createEventWithTaskData(taskData)))
425
+ ).toBe(false);
426
+ });
427
+ });
428
+
429
+ describe('isSelfConferenceTransferInitiator', () => {
430
+ it('returns true when consultingAgentId matches self even if isConsulted is true', () => {
431
+ const ctx = createContext({consultInitiator: false, transferConferenceRequested: false});
432
+ const taskData = createTaskData({
433
+ isConsulted: true,
434
+ consultingAgentId: 'agent-123',
435
+ });
436
+ expect(
437
+ guards.isSelfConferenceTransferInitiator(createParams(ctx, createEventWithTaskData(taskData)))
438
+ ).toBe(true);
439
+ });
440
+
441
+ it('returns false when consultee has consultState consulting but consultingAgentId is another agent', () => {
442
+ const ctx = createContext({consultInitiator: false, transferConferenceRequested: false});
443
+ const taskData = createTaskData({
444
+ isConsulted: true,
445
+ consultingAgentId: 'agent-456',
446
+ interaction: {
447
+ ...createTaskData().interaction,
448
+ participants: {
449
+ 'agent-123': {...createParticipant('agent-123', 'Agent'), consultState: 'consulting'},
450
+ },
451
+ media: {
452
+ [INTERACTION_ID]: createTaskData().interaction!.media![INTERACTION_ID],
453
+ 'consult-media': {
454
+ mediaResourceId: 'consult-media',
455
+ mediaType: 'telephony',
456
+ mediaMgr: 'media-mgr',
457
+ participants: ['agent-123', 'agent-456'],
458
+ mType: 'consult',
459
+ isHold: false,
460
+ holdTimestamp: null,
461
+ },
462
+ },
463
+ },
464
+ });
465
+ expect(
466
+ guards.isSelfConferenceTransferInitiator(createParams(ctx, createEventWithTaskData(taskData)))
467
+ ).toBe(false);
468
+ });
469
+
470
+ it('returns false for passive observer without consult signals', () => {
471
+ const ctx = createContext({consultInitiator: false, transferConferenceRequested: false});
472
+ const taskData = createTaskData({
473
+ isConsulted: true,
474
+ interaction: {
475
+ ...createTaskData().interaction,
476
+ participants: {
477
+ 'agent-123': createParticipant('agent-123', 'Agent'),
478
+ },
479
+ },
480
+ });
481
+ expect(
482
+ guards.isSelfConferenceTransferInitiator(createParams(ctx, createEventWithTaskData(taskData)))
483
+ ).toBe(false);
484
+ });
485
+ });
486
+
329
487
  describe('Hydration Guards - isInteractionConsulting', () => {
330
488
  it('returns true when interaction state is consulting', () => {
331
489
  const ctx = createContext();