@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.
@@ -15,6 +15,18 @@ const createConfig = () => ({
15
15
  isRecordingEnabled: true,
16
16
  });
17
17
 
18
+ /** Mirrors Task.emitTaskWrapup: publishWrapup spy only runs when context would emit task:wrapup. */
19
+ function createPublishAwareEmitTaskWrapupMock() {
20
+ const publishWrapup = jest.fn();
21
+ const emitTaskWrapup = ({context}: {context: {taskData?: {wrapUpRequired?: boolean}}}) => {
22
+ if (context.taskData?.wrapUpRequired) {
23
+ publishWrapup();
24
+ }
25
+ };
26
+
27
+ return {emitTaskWrapup, publishWrapup};
28
+ }
29
+
18
30
  describe('Task state machine', () => {
19
31
  const startMachine = () => {
20
32
  const actor = createActor(createTaskStateMachine(createConfig()));
@@ -217,6 +229,24 @@ describe('Task state machine', () => {
217
229
  expect(emitTaskEnd).not.toHaveBeenCalled();
218
230
  });
219
231
 
232
+ it('enters WRAPPING_UP on TASK_WRAPUP while HOLD_INITIATING and emits wrap-up once', () => {
233
+ const emitTaskWrapup = jest.fn();
234
+ const service = createActor(
235
+ createTaskStateMachine({...createConfig(), agentId: 'agent-1'}, {actions: {emitTaskWrapup}})
236
+ );
237
+ service.start();
238
+ const taskData = createActiveMainCallTaskData();
239
+
240
+ enterTransientHoldState(service, TaskState.HOLD_INITIATING, taskData);
241
+ service.send({
242
+ type: TaskEvent.TASK_WRAPUP,
243
+ taskData: {...taskData, wrapUpRequired: true},
244
+ });
245
+
246
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
247
+ expect(emitTaskWrapup).toHaveBeenCalledTimes(1);
248
+ });
249
+
220
250
  it('ignores PARTICIPANT_LEAVE in HOLD_INITIATING when a remote Drop identifies the current agent', () => {
221
251
  const {service, emitTaskEnd} = startMachineWithEndSpy();
222
252
  const taskData = createActiveMainCallTaskData();
@@ -1824,6 +1854,201 @@ describe('Task state machine', () => {
1824
1854
  expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
1825
1855
  });
1826
1856
 
1857
+ const primeConferencing = (service: ReturnType<typeof startMachine>, taskData: ReturnType<typeof createTaskData>) => {
1858
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
1859
+ service.send({type: TaskEvent.ASSIGN, taskData});
1860
+ service.send({
1861
+ type: TaskEvent.CONSULT,
1862
+ destination: 'agent-42',
1863
+ destinationType: 'agent',
1864
+ });
1865
+ service.send({type: TaskEvent.CONSULT_SUCCESS, taskData});
1866
+ service.send({type: TaskEvent.MERGE_TO_CONFERENCE});
1867
+ service.send({type: TaskEvent.CONFERENCE_START, taskData});
1868
+ expect(service.getSnapshot().value).toBe(TaskState.CONFERENCING);
1869
+ };
1870
+
1871
+ const conferenceInProgressTaskData = (overrides: Parameters<typeof createTaskData>[0] = {}) =>
1872
+ createTaskData({
1873
+ wrapUpRequired: true,
1874
+ interaction: {
1875
+ owner: 'agent-1',
1876
+ state: 'conference',
1877
+ mainInteractionId: 'interaction-1',
1878
+ interactionId: 'interaction-1',
1879
+ participants: {
1880
+ 'agent-1': {
1881
+ id: 'agent-1',
1882
+ pType: 'Agent',
1883
+ type: 'Agent',
1884
+ hasJoined: true,
1885
+ hasLeft: false,
1886
+ },
1887
+ 'agent-2': {
1888
+ id: 'agent-2',
1889
+ pType: 'Agent',
1890
+ type: 'Agent',
1891
+ hasJoined: true,
1892
+ hasLeft: false,
1893
+ },
1894
+ },
1895
+ media: {
1896
+ 'interaction-1': {
1897
+ mediaResourceId: 'interaction-1',
1898
+ mediaType: 'telephony',
1899
+ participants: ['agent-1', 'agent-2'],
1900
+ mType: 'mainCall',
1901
+ isHold: false,
1902
+ },
1903
+ },
1904
+ } as any,
1905
+ ...overrides,
1906
+ });
1907
+
1908
+ const primeConnectedWithConferenceTaskData = (
1909
+ service: ReturnType<typeof startMachine>,
1910
+ taskData: ReturnType<typeof createTaskData>
1911
+ ) => {
1912
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
1913
+ service.send({type: TaskEvent.ASSIGN, taskData});
1914
+ expect(service.getSnapshot().value).toBe(TaskState.CONNECTED);
1915
+ };
1916
+
1917
+ it('enters WRAPPING_UP on EXIT_CONFERENCE_SUCCESS while CONNECTED with conference in task data', () => {
1918
+ const service = startMachine();
1919
+ const taskData = conferenceInProgressTaskData();
1920
+
1921
+ primeConnectedWithConferenceTaskData(service, taskData);
1922
+ service.send({type: TaskEvent.EXIT_CONFERENCE_SUCCESS, taskData});
1923
+
1924
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
1925
+ expect(service.getSnapshot().context.taskData?.wrapUpRequired).toBe(true);
1926
+ });
1927
+
1928
+ it('emits wrap-up once on EXIT_CONFERENCE_SUCCESS while CONNECTED', () => {
1929
+ const emitTaskWrapup = jest.fn();
1930
+ const service = createActor(
1931
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
1932
+ );
1933
+ service.start();
1934
+ const taskData = conferenceInProgressTaskData();
1935
+
1936
+ primeConnectedWithConferenceTaskData(service, taskData);
1937
+ service.send({type: TaskEvent.EXIT_CONFERENCE_SUCCESS, taskData});
1938
+
1939
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
1940
+ expect(emitTaskWrapup).toHaveBeenCalledTimes(1);
1941
+ });
1942
+
1943
+ it('terminates on EXIT_CONFERENCE_SUCCESS while CONNECTED when wrap-up is not required', () => {
1944
+ const service = startMachine();
1945
+ const taskData = conferenceInProgressTaskData({
1946
+ wrapUpRequired: false,
1947
+ interaction: {
1948
+ owner: 'other-agent',
1949
+ state: 'conference',
1950
+ mainInteractionId: 'interaction-1',
1951
+ interactionId: 'interaction-1',
1952
+ participants: {
1953
+ 'agent-1': {
1954
+ id: 'agent-1',
1955
+ pType: 'Agent',
1956
+ type: 'Agent',
1957
+ hasJoined: true,
1958
+ hasLeft: false,
1959
+ isWrapUp: false,
1960
+ },
1961
+ 'agent-2': {
1962
+ id: 'agent-2',
1963
+ pType: 'Agent',
1964
+ type: 'Agent',
1965
+ hasJoined: true,
1966
+ hasLeft: false,
1967
+ },
1968
+ },
1969
+ media: {
1970
+ 'interaction-1': {
1971
+ mediaResourceId: 'interaction-1',
1972
+ mediaType: 'telephony',
1973
+ participants: ['agent-1', 'agent-2'],
1974
+ mType: 'mainCall',
1975
+ isHold: false,
1976
+ },
1977
+ },
1978
+ } as any,
1979
+ });
1980
+
1981
+ primeConnectedWithConferenceTaskData(service, taskData);
1982
+ service.send({type: TaskEvent.EXIT_CONFERENCE_SUCCESS, taskData});
1983
+
1984
+ expect(service.getSnapshot().value).toBe(TaskState.TERMINATED);
1985
+ });
1986
+
1987
+ it('does not re-emit wrap-up on late TASK_WRAPUP when wrap-up was already published', () => {
1988
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
1989
+ const service = createActor(
1990
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
1991
+ );
1992
+ service.start();
1993
+ const taskData = conferenceInProgressTaskData();
1994
+
1995
+ primeConferencing(service, taskData);
1996
+ service.send({
1997
+ type: TaskEvent.EXIT_CONFERENCE_SUCCESS,
1998
+ taskData: {...taskData, wrapUpRequired: true},
1999
+ });
2000
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2001
+ expect(service.getSnapshot().context.taskData?.wrapUpRequired).toBe(true);
2002
+
2003
+ const emitCountAfterExit = publishWrapup.mock.calls.length;
2004
+ service.send({
2005
+ type: TaskEvent.TASK_WRAPUP,
2006
+ taskData: {...taskData, wrapUpRequired: true},
2007
+ });
2008
+
2009
+ expect(publishWrapup.mock.calls.length).toBe(emitCountAfterExit);
2010
+ });
2011
+
2012
+ it('emits wrap-up on late TASK_WRAPUP when wrap-up was not yet published', () => {
2013
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
2014
+ const service = createActor(
2015
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2016
+ );
2017
+ service.start();
2018
+ const taskData = createTaskData({
2019
+ wrapUpRequired: false,
2020
+ interaction: {
2021
+ owner: 'agent-1',
2022
+ state: 'connected',
2023
+ mainInteractionId: 'interaction-1',
2024
+ interactionId: 'interaction-1',
2025
+ participants: {
2026
+ 'agent-1': {
2027
+ id: 'agent-1',
2028
+ pType: 'Agent',
2029
+ type: 'Agent',
2030
+ hasJoined: true,
2031
+ hasLeft: false,
2032
+ },
2033
+ },
2034
+ } as any,
2035
+ });
2036
+
2037
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
2038
+ service.send({type: TaskEvent.ASSIGN, taskData});
2039
+ service.send({type: TaskEvent.TASK_WRAPUP, taskData});
2040
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2041
+ expect(service.getSnapshot().context.taskData?.wrapUpRequired).not.toBe(true);
2042
+ expect(publishWrapup).not.toHaveBeenCalled();
2043
+
2044
+ service.send({
2045
+ type: TaskEvent.TASK_WRAPUP,
2046
+ taskData: {...taskData, wrapUpRequired: true},
2047
+ });
2048
+
2049
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
2050
+ });
2051
+
1827
2052
  it('terminates when EXIT_CONFERENCE_SUCCESS is received in conferencing and wrapup is not required', () => {
1828
2053
  const service = startMachine();
1829
2054
  const taskData = createTaskData({
@@ -1883,6 +2108,254 @@ describe('Task state machine', () => {
1883
2108
  expect(service.getSnapshot().value).toBe(TaskState.TERMINATED);
1884
2109
  });
1885
2110
 
2111
+ it('enters WRAPPING_UP on CONFERENCE_END when wrapUpRequired is stamped', () => {
2112
+ const service = startMachine();
2113
+ const taskData = createTaskData({
2114
+ wrapUpRequired: true,
2115
+ interaction: {
2116
+ owner: 'agent-1',
2117
+ state: 'conference',
2118
+ mainInteractionId: 'interaction-1',
2119
+ interactionId: 'interaction-1',
2120
+ participants: {
2121
+ 'agent-1': {
2122
+ id: 'agent-1',
2123
+ pType: 'Agent',
2124
+ type: 'Agent',
2125
+ isWrapUp: true,
2126
+ hasJoined: true,
2127
+ hasLeft: true,
2128
+ },
2129
+ },
2130
+ } as any,
2131
+ });
2132
+
2133
+ primeConferencing(service, taskData);
2134
+ service.send({type: TaskEvent.CONFERENCE_END, taskData});
2135
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2136
+ });
2137
+
2138
+ it('emits wrap-up once on CONFERENCE_END when wrap-up is required', () => {
2139
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
2140
+ const service = createActor(
2141
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2142
+ );
2143
+ service.start();
2144
+ const taskData = createTaskData({
2145
+ wrapUpRequired: true,
2146
+ interaction: {
2147
+ owner: 'agent-1',
2148
+ state: 'conference',
2149
+ mainInteractionId: 'interaction-1',
2150
+ interactionId: 'interaction-1',
2151
+ participants: {
2152
+ 'agent-1': {
2153
+ id: 'agent-1',
2154
+ pType: 'Agent',
2155
+ type: 'Agent',
2156
+ isWrapUp: true,
2157
+ hasJoined: true,
2158
+ hasLeft: true,
2159
+ },
2160
+ },
2161
+ } as any,
2162
+ });
2163
+
2164
+ primeConferencing(service, taskData);
2165
+ service.send({type: TaskEvent.CONFERENCE_END, taskData});
2166
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2167
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
2168
+ });
2169
+
2170
+ it('emits wrap-up once on TASK_WRAPUP from CONSULTING when wrap-up is required', () => {
2171
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
2172
+ const service = createActor(
2173
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2174
+ );
2175
+ service.start();
2176
+ const taskData = createTaskData({
2177
+ interaction: {owner: 'agent-1', state: 'connected'} as any,
2178
+ });
2179
+
2180
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
2181
+ service.send({type: TaskEvent.ASSIGN, taskData});
2182
+ service.send({type: TaskEvent.CONSULT, destination: 'agent-2', destinationType: 'agent'});
2183
+ service.send({type: TaskEvent.CONSULT_SUCCESS, taskData});
2184
+ expect(service.getSnapshot().value).toBe(TaskState.CONSULTING);
2185
+
2186
+ service.send({
2187
+ type: TaskEvent.TASK_WRAPUP,
2188
+ taskData: {...taskData, wrapUpRequired: true},
2189
+ });
2190
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2191
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
2192
+ });
2193
+
2194
+ it('emits wrap-up once on TASK_WRAPUP from CONFERENCING when wrap-up is required', () => {
2195
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
2196
+ const service = createActor(
2197
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2198
+ );
2199
+ service.start();
2200
+ const taskData = createTaskData({
2201
+ interaction: {
2202
+ owner: 'agent-1',
2203
+ state: 'conference',
2204
+ mainInteractionId: 'interaction-1',
2205
+ interactionId: 'interaction-1',
2206
+ } as any,
2207
+ });
2208
+
2209
+ primeConferencing(service, taskData);
2210
+ service.send({
2211
+ type: TaskEvent.TASK_WRAPUP,
2212
+ taskData: {...taskData, wrapUpRequired: true},
2213
+ });
2214
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2215
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
2216
+ });
2217
+
2218
+ it('enters WRAPPING_UP on PARTICIPANT_LEAVE when this agent left and wrap-up is required', () => {
2219
+ const service = startMachine();
2220
+ const conferenceData = createTaskData({
2221
+ interaction: {
2222
+ owner: 'agent-1',
2223
+ state: 'conference',
2224
+ mainInteractionId: 'interaction-1',
2225
+ interactionId: 'interaction-1',
2226
+ participants: {
2227
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2228
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2229
+ },
2230
+ } as any,
2231
+ });
2232
+ const leaveData = createTaskData({
2233
+ wrapUpRequired: true,
2234
+ participantId: 'agent-1',
2235
+ interaction: {
2236
+ owner: 'agent-1',
2237
+ state: 'conference',
2238
+ mainInteractionId: 'interaction-1',
2239
+ interactionId: 'interaction-1',
2240
+ participants: {
2241
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2242
+ },
2243
+ } as any,
2244
+ });
2245
+
2246
+ primeConferencing(service, conferenceData);
2247
+ service.send({
2248
+ type: TaskEvent.PARTICIPANT_LEAVE,
2249
+ participantId: 'agent-1',
2250
+ taskData: leaveData,
2251
+ });
2252
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2253
+ });
2254
+
2255
+ it('emits wrap-up once on PARTICIPANT_LEAVE when wrap-up is required', () => {
2256
+ const emitTaskWrapup = jest.fn();
2257
+ const service = createActor(
2258
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2259
+ );
2260
+ service.start();
2261
+ const conferenceData = createTaskData({
2262
+ interaction: {
2263
+ owner: 'agent-1',
2264
+ state: 'conference',
2265
+ mainInteractionId: 'interaction-1',
2266
+ interactionId: 'interaction-1',
2267
+ participants: {
2268
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2269
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2270
+ },
2271
+ } as any,
2272
+ });
2273
+ const leaveData = createTaskData({
2274
+ wrapUpRequired: true,
2275
+ participantId: 'agent-1',
2276
+ interaction: {
2277
+ owner: 'agent-1',
2278
+ state: 'conference',
2279
+ mainInteractionId: 'interaction-1',
2280
+ interactionId: 'interaction-1',
2281
+ participants: {
2282
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2283
+ },
2284
+ } as any,
2285
+ });
2286
+
2287
+ primeConferencing(service, conferenceData);
2288
+ service.send({
2289
+ type: TaskEvent.PARTICIPANT_LEAVE,
2290
+ participantId: 'agent-1',
2291
+ taskData: leaveData,
2292
+ });
2293
+
2294
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2295
+ expect(emitTaskWrapup).toHaveBeenCalledTimes(1);
2296
+ });
2297
+
2298
+ it('does not wrap remaining agent on PARTICIPANT_LEAVE', () => {
2299
+ const service = startMachine();
2300
+ const conferenceData = createTaskData({
2301
+ interaction: {
2302
+ owner: 'agent-1',
2303
+ state: 'conference',
2304
+ mainInteractionId: 'interaction-1',
2305
+ interactionId: 'interaction-1',
2306
+ participants: {
2307
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2308
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2309
+ c1: {id: 'c1', pType: 'Customer', type: 'Customer', hasJoined: true, hasLeft: false},
2310
+ },
2311
+ media: {
2312
+ 'interaction-1': {
2313
+ mediaResourceId: 'interaction-1',
2314
+ mediaType: 'telephony',
2315
+ mediaMgr: 'mm',
2316
+ participants: ['agent-1', 'agent-2', 'c1'],
2317
+ mType: 'mainCall',
2318
+ isHold: false,
2319
+ holdTimestamp: null,
2320
+ },
2321
+ },
2322
+ } as any,
2323
+ });
2324
+ const otherLeft = createTaskData({
2325
+ wrapUpRequired: false,
2326
+ participantId: 'agent-2',
2327
+ interaction: {
2328
+ owner: 'agent-1',
2329
+ state: 'conference',
2330
+ mainInteractionId: 'interaction-1',
2331
+ interactionId: 'interaction-1',
2332
+ participants: {
2333
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
2334
+ c1: {id: 'c1', pType: 'Customer', type: 'Customer', hasJoined: true, hasLeft: false},
2335
+ },
2336
+ media: {
2337
+ 'interaction-1': {
2338
+ mediaResourceId: 'interaction-1',
2339
+ mediaType: 'telephony',
2340
+ mediaMgr: 'mm',
2341
+ participants: ['agent-1', 'c1'],
2342
+ mType: 'mainCall',
2343
+ isHold: false,
2344
+ holdTimestamp: null,
2345
+ },
2346
+ },
2347
+ } as any,
2348
+ });
2349
+
2350
+ primeConferencing(service, conferenceData);
2351
+ service.send({
2352
+ type: TaskEvent.PARTICIPANT_LEAVE,
2353
+ participantId: 'agent-2',
2354
+ taskData: otherLeft,
2355
+ });
2356
+ expect(service.getSnapshot().value).not.toBe(TaskState.WRAPPING_UP);
2357
+ });
2358
+
1886
2359
  it('downgrades to HELD on HOLD_SUCCESS when no other agents remain on task', () => {
1887
2360
  const service = startMachine();
1888
2361
  const conferenceTaskData = createSingleAgentConferenceTaskData('conference');
@@ -2471,6 +2944,28 @@ describe('Task state machine', () => {
2471
2944
  service.send({type: TaskEvent.TASK_WRAPUP, taskData: wrapupTaskData});
2472
2945
  expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2473
2946
  });
2947
+
2948
+ it('emits wrap-up once on TASK_WRAPUP from OFFERED when wrapup is required', () => {
2949
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
2950
+ const service = createActor(
2951
+ createTaskStateMachine(createConfig(), {actions: {emitTaskWrapup}})
2952
+ );
2953
+ service.start();
2954
+ const offerTaskData = createTaskData({
2955
+ interaction: {outboundType: 'OUTDIAL'} as any,
2956
+ });
2957
+ service.send({type: TaskEvent.TASK_INCOMING, taskData: offerTaskData});
2958
+ expect(service.getSnapshot().value).toBe(TaskState.OFFERED);
2959
+
2960
+ const wrapupTaskData = createTaskData({
2961
+ agentId: 'agent-1',
2962
+ wrapUpRequired: true,
2963
+ interaction: {outboundType: 'OUTDIAL', state: 'wrapUp', isTerminated: true} as any,
2964
+ });
2965
+ service.send({type: TaskEvent.TASK_WRAPUP, taskData: wrapupTaskData});
2966
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
2967
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
2968
+ });
2474
2969
  });
2475
2970
 
2476
2971
  describe('OUTBOUND_FAILED handling', () => {
@@ -3218,6 +3713,79 @@ describe('Task state machine', () => {
3218
3713
  expect(service.getSnapshot().value).toBe(TaskState.TERMINATED);
3219
3714
  });
3220
3715
 
3716
+ it('emits wrap-up once on TRANSFER_CONFERENCE_SUCCESS from CONSULTING when wrap-up is required', () => {
3717
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
3718
+ const service = createActor(
3719
+ createTaskStateMachine({...createConfig(), agentId: 'agent-1'}, {actions: {emitTaskWrapup}})
3720
+ );
3721
+ service.start();
3722
+ const taskData = createTaskData({
3723
+ agentId: 'agent-1',
3724
+ consultingAgentId: 'agent-1',
3725
+ interaction: {
3726
+ owner: 'agent-1',
3727
+ state: 'conference',
3728
+ mainInteractionId: 'interaction-1',
3729
+ interactionId: 'interaction-1',
3730
+ participants: {
3731
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
3732
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
3733
+ },
3734
+ } as any,
3735
+ });
3736
+
3737
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
3738
+ service.send({type: TaskEvent.ASSIGN, taskData});
3739
+ service.send({type: TaskEvent.CONSULT, destination: 'agent-2', destinationType: 'agent'});
3740
+ service.send({type: TaskEvent.CONSULT_SUCCESS, taskData});
3741
+ expect(service.getSnapshot().value).toBe(TaskState.CONSULTING);
3742
+
3743
+ service.send({type: TaskEvent.TRANSFER_CONFERENCE});
3744
+ service.send({
3745
+ type: TaskEvent.TRANSFER_CONFERENCE_SUCCESS,
3746
+ taskData: {...taskData, wrapUpRequired: true},
3747
+ });
3748
+
3749
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
3750
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
3751
+ });
3752
+
3753
+ it('emits wrap-up once on TRANSFER_CONFERENCE_SUCCESS from CONFERENCING when wrap-up is required', () => {
3754
+ const {emitTaskWrapup, publishWrapup} = createPublishAwareEmitTaskWrapupMock();
3755
+ const service = createActor(
3756
+ createTaskStateMachine({...createConfig(), agentId: 'agent-1'}, {actions: {emitTaskWrapup}})
3757
+ );
3758
+ service.start();
3759
+ const taskData = createTaskData({
3760
+ agentId: 'agent-1',
3761
+ interaction: {
3762
+ owner: 'agent-1',
3763
+ state: 'conference',
3764
+ mainInteractionId: 'interaction-1',
3765
+ interactionId: 'interaction-1',
3766
+ participants: {
3767
+ 'agent-1': {id: 'agent-1', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
3768
+ 'agent-2': {id: 'agent-2', pType: 'Agent', type: 'Agent', hasJoined: true, hasLeft: false},
3769
+ },
3770
+ } as any,
3771
+ });
3772
+
3773
+ service.send({type: TaskEvent.TASK_INCOMING, taskData});
3774
+ service.send({type: TaskEvent.ASSIGN, taskData});
3775
+ service.send({type: TaskEvent.MERGE_TO_CONFERENCE});
3776
+ service.send({type: TaskEvent.CONFERENCE_START, taskData});
3777
+ expect(service.getSnapshot().value).toBe(TaskState.CONFERENCING);
3778
+
3779
+ service.send({type: TaskEvent.TRANSFER_CONFERENCE});
3780
+ service.send({
3781
+ type: TaskEvent.TRANSFER_CONFERENCE_SUCCESS,
3782
+ taskData: {...taskData, wrapUpRequired: true},
3783
+ });
3784
+
3785
+ expect(service.getSnapshot().value).toBe(TaskState.WRAPPING_UP);
3786
+ expect(publishWrapup).toHaveBeenCalledTimes(1);
3787
+ });
3788
+
3221
3789
  it('terminates secondary agent on PARTICIPANT_LEAVE while in CONSULTING during conference', () => {
3222
3790
  const service = startAgent2Machine();
3223
3791
  setupSecondaryAgentDesktopConsultingFromConference(service);