@webex/contact-center 3.12.0-next.122 → 3.12.0-next.124

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.
@@ -94,8 +94,11 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
94
94
  - `CONSULTING_ACTIVE` -> `CONSULTING`
95
95
  - Guard: none
96
96
  - Actions: `updateTaskData`, `setConsultAgentJoined`, `emitTaskConsultAccepted`, `emitTaskConsulting`
97
- - `TASK_WRAPUP` -> `TERMINATED`
98
- - Guard: none
97
+ - `TASK_WRAPUP` -> `WRAPPING_UP`
98
+ - Guard: `guards.shouldWrapUp`
99
+ - Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
100
+ - `TASK_WRAPUP` -> `TERMINATED` (default branch)
101
+ - Guard: default
99
102
  - Actions: `updateTaskData`, `markEnded`, `emitTaskEnd`
100
103
  - `RONA` / `ASSIGN_FAILED` / `INVITE_FAILED` / `OUTBOUND_FAILED` -> `TERMINATED`
101
104
  - Guard: none
@@ -159,7 +162,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
159
162
  - Actions: `updateTaskData`, `markEnded`, `emitTaskEnd`
160
163
  - `TASK_WRAPUP` -> `WRAPPING_UP`
161
164
  - Guard: none
162
- - Actions: `updateTaskData`, `markEnded`, `emitTaskWrapup`
165
+ - Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
163
166
  - `PAUSE_RECORDING` / `RESUME_RECORDING` -> Stay `CONNECTED`
164
167
  - Guard: none
165
168
  - Actions: `updateTaskData`, `setRecordingState`, `emitTaskRecordingPaused` / `emitTaskRecordingResumed`
@@ -366,7 +369,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
366
369
  - Actions: `updateTaskData`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`
367
370
  - `TRANSFER_CONFERENCE_SUCCESS` -> `WRAPPING_UP`
368
371
  - Guard: `guards.shouldWrapUp`
369
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`, `emitTaskWrapup`
372
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
370
373
  - `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
371
374
  - Guard: inline `!context.consultInitiator`
372
375
  - Actions: `updateTaskData`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`
@@ -384,7 +387,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
384
387
  - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`, `requestCleanup`
385
388
  - `TASK_WRAPUP` -> `WRAPPING_UP`
386
389
  - Guard: none
387
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`
390
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
388
391
  - `MERGE_TO_CONFERENCE` -> `CONF_INITIATING`
389
392
  - Guard: none
390
393
  - Actions: none
@@ -465,7 +468,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
465
468
  - Actions: `clearTransferConferenceRequested`
466
469
  - `PARTICIPANT_LEAVE` -> `WRAPPING_UP`
467
470
  - Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
468
- - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskWrapup`
471
+ - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
469
472
  - `PARTICIPANT_LEAVE` -> `TERMINATED`
470
473
  - Guard: `guards.didCurrentAgentLeaveMainInteraction`
471
474
  - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskEnd`
@@ -483,15 +486,21 @@ is not treated as departure. `PARTICIPANT_LEAVE` is handled in `HELD`,
483
486
  `RESUME_INITIATING`, `CONSULTING`, `CONSULT_INITIATING`, and `CONFERENCING`;
484
487
  `CONNECTED`, `HOLD_INITIATING`, and `CONF_INITIATING` ignore the event.
485
488
 
489
+ - `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
490
+ - Guard: `guards.shouldWrapUp` or default
491
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd` on terminate; `WRAPPING_UP` entry emits `task:wrapup` (shared helper on `CONNECTED`, `HELD`, and `CONFERENCING` for Voice HTTP exit)
486
492
  - `CONFERENCE_END` -> `WRAPPING_UP`
487
493
  - Guard: `guards.shouldWrapUp`
488
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`
494
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
489
495
  - `CONFERENCE_END` -> `CONNECTED`
490
496
  - Guard: inline `!context.exitingConference && customerInCall`
491
497
  - Actions: `updateTaskData`, `clearConsultState`, `emitTaskConferenceEnded`
492
498
  - `CONFERENCE_END` -> `TERMINATED` (default branch)
493
499
  - Guard: default
494
500
  - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskEnd`
501
+ - `TASK_WRAPUP` -> `WRAPPING_UP`
502
+ - Guard: `guards.shouldWrapUp`
503
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
495
504
  - `CONTACT_ENDED` -> stay `CONFERENCING`
496
505
  - Guard: none
497
506
  - Actions: `updateTaskData`, `requestCleanup`
@@ -513,6 +522,8 @@ is not treated as departure. `PARTICIPANT_LEAVE` is handled in `HELD`,
513
522
 
514
523
  **Valid transitions from `WRAPPING_UP`**:
515
524
 
525
+ - `TASK_WRAPUP` -> stay `WRAPPING_UP`
526
+ - Guard: if `context.taskData.wrapUpRequired === true`, `updateTaskData` only; else `updateTaskData`, `emitTaskWrapup`
516
527
  - `WRAPUP_COMPLETE` -> `COMPLETED`
517
528
  - Guard: none
518
529
  - Actions: `updateTaskData`
@@ -874,7 +874,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
874
874
 
875
875
  - Guard: `guards.shouldWrapUp`
876
876
 
877
- - Actions: `updateTaskData`, `markEnded`, `emitTaskWrapup`
877
+ - Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
878
878
 
879
879
  - `TASK_WRAPUP` -> `TERMINATED`
880
880
 
@@ -988,7 +988,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
988
988
 
989
989
  - Guard: none
990
990
 
991
- - Actions: `updateTaskData`, `markEnded`, `emitTaskWrapup`
991
+ - Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
992
992
 
993
993
  - `PAUSE_RECORDING` / `RESUME_RECORDING` -> Stay `CONNECTED`
994
994
 
@@ -996,6 +996,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
996
996
 
997
997
  - Actions: `updateTaskData`, `setRecordingState`, `emitTaskRecordingPaused` / `emitTaskRecordingResumed`
998
998
 
999
+ - `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
1000
+
1001
+ - Guard: `guards.shouldWrapUp` (wrap-up branch) or default (terminate)
1002
+
1003
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (same as `CONFERENCING`; Voice `exitConference()` while actor stays `CONNECTED` with conference in task data)
1004
+
999
1005
  **Description**: Main call is on hold.
1000
1006
 
1001
1007
  **How this state is reached (incoming transitions)**:
@@ -1090,7 +1096,13 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1090
1096
 
1091
1097
  - Guard: none
1092
1098
 
1093
- - Actions: `updateTaskData`, `markEnded`, `emitTaskWrapup`
1099
+ - Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
1100
+
1101
+ - `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
1102
+
1103
+ - Guard: `guards.shouldWrapUp` or default
1104
+
1105
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (shared with `CONNECTED` / `CONFERENCING`)
1094
1106
 
1095
1107
  **Description**: Hold request has been sent and is awaiting backend confirmation.
1096
1108
 
@@ -1116,6 +1128,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1116
1128
 
1117
1129
  - Actions: `updateTaskData`
1118
1130
 
1131
+ - `TASK_WRAPUP` -> `WRAPPING_UP`
1132
+
1133
+ - Guard: none
1134
+
1135
+ - Actions: `updateTaskData`, `markEnded` (`WRAPPING_UP` entry emits `task:wrapup`)
1136
+
1119
1137
  **Description**: Resume/unhold request has been sent and is awaiting backend confirmation.
1120
1138
 
1121
1139
  **How this state is reached (incoming transitions)**:
@@ -1140,6 +1158,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1140
1158
 
1141
1159
  - Actions: none
1142
1160
 
1161
+ - `TASK_WRAPUP` -> `WRAPPING_UP`
1162
+
1163
+ - Guard: none
1164
+
1165
+ - Actions: `updateTaskData`, `markEnded` (`WRAPPING_UP` entry emits `task:wrapup`)
1166
+
1143
1167
  **Description**: Consult request is in-flight.
1144
1168
 
1145
1169
  **How this state is reached (incoming transitions)**:
@@ -1306,7 +1330,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1306
1330
 
1307
1331
  - Guard: `guards.shouldWrapUp`
1308
1332
 
1309
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`, `emitTaskWrapup`
1333
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
1310
1334
 
1311
1335
  - `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
1312
1336
 
@@ -1330,7 +1354,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1330
1354
 
1331
1355
  - Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
1332
1356
 
1333
- - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskWrapup`
1357
+ - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
1334
1358
 
1335
1359
  - `PARTICIPANT_LEAVE` -> `TERMINATED`
1336
1360
 
@@ -1366,7 +1390,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1366
1390
 
1367
1391
  - Guard: none
1368
1392
 
1369
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`
1393
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
1370
1394
 
1371
1395
  - `MERGE_TO_CONFERENCE` -> `CONF_INITIATING`
1372
1396
 
@@ -1458,6 +1482,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1458
1482
 
1459
1483
  - Actions: `updateTaskData`, `clearConsultState`, `emitTaskConferenceStarted`
1460
1484
 
1485
+ - `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
1486
+
1487
+ - Guard: `guards.shouldWrapUp` or default
1488
+
1489
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (shared with `CONNECTED` / `HELD`)
1490
+
1461
1491
  - `CONSULT_END` -> stay `CONFERENCING`
1462
1492
 
1463
1493
  - Guard: none
@@ -1486,7 +1516,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1486
1516
 
1487
1517
  - Guard: `guards.shouldWrapUp`
1488
1518
 
1489
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`, `emitTaskWrapup`
1519
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
1490
1520
 
1491
1521
  - `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
1492
1522
 
@@ -1510,7 +1540,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1510
1540
 
1511
1541
  - Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
1512
1542
 
1513
- - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskWrapup`
1543
+ - Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
1514
1544
 
1515
1545
  - `PARTICIPANT_LEAVE` -> `TERMINATED`
1516
1546
 
@@ -1542,7 +1572,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1542
1572
 
1543
1573
  - Guard: `guards.shouldWrapUp`
1544
1574
 
1545
- - Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`
1575
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
1546
1576
 
1547
1577
  - `CONFERENCE_END` -> `CONNECTED`
1548
1578
 
@@ -1562,6 +1592,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1562
1592
 
1563
1593
  - Actions: `updateTaskData`, `requestCleanup`
1564
1594
 
1595
+ - `TASK_WRAPUP` -> `WRAPPING_UP`
1596
+
1597
+ - Guard: `guards.shouldWrapUp`
1598
+
1599
+ - Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
1600
+
1565
1601
  **Description**: Post-interaction work (ACW) is in progress.
1566
1602
 
1567
1603
  **How this state is reached (incoming transitions)**:
@@ -1576,6 +1612,10 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
1576
1612
 
1577
1613
  **Valid transitions from `WRAPPING_UP`**:
1578
1614
 
1615
+ - `TASK_WRAPUP` -> stay `WRAPPING_UP`
1616
+
1617
+ - Guard: if `context.taskData.wrapUpRequired === true` before the event, actions are `updateTaskData` only; otherwise `updateTaskData`, `emitTaskWrapup` (late AgentWrapup after wrap-up was already published)
1618
+
1579
1619
  - `WRAPUP_COMPLETE` -> `COMPLETED`
1580
1620
 
1581
1621
  - Guard: none
@@ -28,7 +28,8 @@ import Task from '../Task';
28
28
  import LoggerProxy from '../../../logger-proxy';
29
29
  import MetricsManager from '../../../metrics/MetricsManager';
30
30
  import {METRIC_EVENT_NAMES} from '../../../metrics/constants';
31
- import {TaskState, TaskEvent, TaskActionArgs} from '../state-machine';
31
+ import {TaskState, TaskEvent, TaskActionArgs, type TaskContext} from '../state-machine';
32
+ import {shouldWrapUpForThisAgent} from '../state-machine/guards';
32
33
  import {WrapupData} from '../../config/types';
33
34
  import {getConsultMediaResourceId, getIsConferenceInProgress} from '../TaskUtils';
34
35
  import AnswerCallOnWebexService from '../../AnswerCallOnWebexService';
@@ -56,6 +57,24 @@ import {
56
57
  WxAppAcceptReason,
57
58
  } from '../../wxAppDiagnosticLogging';
58
59
 
60
+ const hasNonemptyPendingWrapUp = (taskData?: TaskData): boolean =>
61
+ Array.isArray(taskData?.agentsPendingWrapUp) && taskData.agentsPendingWrapUp.length > 0;
62
+
63
+ /**
64
+ * Same consulted-non-owner rule as TaskManager leave stamp. Used only for the
65
+ * HTTP exitConference self-exit fallback (shouldWrapUpForThisAgent stays unchanged).
66
+ */
67
+ const isConsultedNonOwner = (taskData: TaskData, fallback?: TaskData): boolean => {
68
+ const isConsulted = taskData.isConsulted ?? fallback?.isConsulted;
69
+ if (isConsulted !== true) {
70
+ return false;
71
+ }
72
+ const owner = taskData.interaction?.owner ?? fallback?.interaction?.owner;
73
+ const selfAgentId = taskData.agentId ?? fallback?.agentId;
74
+
75
+ return Boolean(selfAgentId && owner && owner !== selfAgentId);
76
+ };
77
+
59
78
  export default class Voice extends Task implements IVoice {
60
79
  private static readonly WXAPP_MUTE_SYNC_RETRY_DELAY_MS = 50;
61
80
  private static readonly WXAPP_MUTE_SYNC_MAX_RETRIES = 3;
@@ -1426,9 +1445,32 @@ export default class Voice extends Task implements IVoice {
1426
1445
 
1427
1446
  // Send success event to transition state
1428
1447
  if (this.stateMachineService) {
1448
+ const responseTaskData = (response?.data ?? {}) as TaskData;
1449
+ const snapshot = this.stateMachineService.getSnapshot();
1450
+ const wrapUpContext = (snapshot?.context ?? {
1451
+ uiControlConfig: this.uiControlConfig,
1452
+ taskData: this.data,
1453
+ }) as TaskContext;
1454
+ const mergedTaskData = {
1455
+ ...this.data,
1456
+ ...responseTaskData,
1457
+ };
1458
+ // Pending-list precedence is response-only; do not keep a cached snapshot list.
1459
+ if (!Object.prototype.hasOwnProperty.call(responseTaskData, 'agentsPendingWrapUp')) {
1460
+ delete mergedTaskData.agentsPendingWrapUp;
1461
+ }
1462
+ let wrapUpRequired = shouldWrapUpForThisAgent(wrapUpContext, mergedTaskData);
1463
+ // Confirmed self-exit: empty/absent response pending matches TaskManager leave stamp.
1464
+ if (!wrapUpRequired && !hasNonemptyPendingWrapUp(responseTaskData)) {
1465
+ wrapUpRequired = !isConsultedNonOwner(mergedTaskData, this.data);
1466
+ }
1467
+
1429
1468
  this.stateMachineService.send({
1430
1469
  type: TaskEvent.EXIT_CONFERENCE_SUCCESS,
1431
- taskData: response.data,
1470
+ taskData: {
1471
+ ...responseTaskData,
1472
+ wrapUpRequired,
1473
+ },
1432
1474
  });
1433
1475
  }
1434
1476
 
@@ -13,12 +13,18 @@ import LoggerProxy from '../../../../../src/logger-proxy';
13
13
  import {createTaskData} from './taskTestUtils';
14
14
 
15
15
  class DummyTask extends Task {
16
- constructor(contact: any, data: TaskData) {
17
- super(contact, data, {
18
- channelType: 'voice',
19
- isEndTaskEnabled: true,
20
- isEndConsultEnabled: true,
21
- });
16
+ constructor(contact: any, data: TaskData, wrapupData?: any, agentId?: string) {
17
+ super(
18
+ contact,
19
+ data,
20
+ {
21
+ channelType: 'voice',
22
+ isEndTaskEnabled: true,
23
+ isEndConsultEnabled: true,
24
+ },
25
+ wrapupData,
26
+ agentId
27
+ );
22
28
  }
23
29
 
24
30
  public accept() {
@@ -250,6 +256,68 @@ describe('Task (base class)', () => {
250
256
  expect(emitSpy).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_WRAPUP, task);
251
257
  });
252
258
 
259
+ it('starts auto wrap-up only when wrapUpRequired is true and profile autoWrapup is enabled', () => {
260
+ const wrapUpProps = {
261
+ autoWrapup: true,
262
+ autoWrapupInterval: 25000,
263
+ wrapUpReasonList: [{id: 'code-1', name: 'Default', isDefault: true, isSystem: false}],
264
+ };
265
+ const enabled = new DummyTask(
266
+ dummyContact,
267
+ createTaskData({wrapUpRequired: false}) as TaskData,
268
+ {wrapUpProps},
269
+ 'agent-1'
270
+ );
271
+
272
+ expect(enabled.autoWrapup).toBeUndefined();
273
+ try {
274
+ enabled.updateTaskData(createTaskData({wrapUpRequired: true}) as TaskData);
275
+ expect(enabled.autoWrapup).toBeDefined();
276
+
277
+ const disabled = new DummyTask(
278
+ dummyContact,
279
+ createTaskData({wrapUpRequired: false}) as TaskData,
280
+ {wrapUpProps: {...wrapUpProps, autoWrapup: false}},
281
+ 'agent-1'
282
+ );
283
+ disabled.updateTaskData(createTaskData({wrapUpRequired: true}) as TaskData);
284
+ expect(disabled.autoWrapup).toBeUndefined();
285
+ } finally {
286
+ enabled.cancelAutoWrapupTimer();
287
+ }
288
+ });
289
+
290
+ it('calls contact.wrapup when the auto wrap-up timer elapses after wrapUpRequired is stamped', async () => {
291
+ const wrapUpProps = {
292
+ autoWrapup: true,
293
+ autoWrapupInterval: 1000,
294
+ wrapUpReasonList: [{id: 'code-1', name: 'Default', isDefault: true, isSystem: false}],
295
+ };
296
+ const contact = {wrapup: jest.fn().mockResolvedValue({result: 'wrap'})};
297
+ const wrappingTask = new DummyTask(
298
+ contact,
299
+ createTaskData({wrapUpRequired: false}) as TaskData,
300
+ {wrapUpProps},
301
+ 'agent-1'
302
+ );
303
+
304
+ jest.useFakeTimers();
305
+ try {
306
+ wrappingTask.updateTaskData(createTaskData({wrapUpRequired: true}) as TaskData);
307
+ expect(wrappingTask.autoWrapup).toBeDefined();
308
+
309
+ jest.advanceTimersByTime(1000);
310
+
311
+ expect(contact.wrapup).toHaveBeenCalledWith({
312
+ interactionId: 'interaction-1',
313
+ data: {wrapUpReason: 'Default', auxCodeId: 'code-1'},
314
+ });
315
+ } finally {
316
+ wrappingTask.cancelAutoWrapupTimer();
317
+ jest.useRealTimers();
318
+ }
319
+ });
320
+
253
321
  it('throws for unsupported voice operations in the base class', async () => {
254
322
  const fullData = createTaskData();
255
323
  const voiceTask = new DummyTask(dummyContact, fullData);