forked from webex/widgets
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadvancedTaskControlUtils.ts
More file actions
180 lines (162 loc) · 6.34 KB
/
Copy pathadvancedTaskControlUtils.ts
File metadata and controls
180 lines (162 loc) · 6.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import {Page} from '@playwright/test';
import {AWAIT_TIMEOUT, FORM_FIELD_TIMEOUT} from '../constants';
/**
* Utility functions for advanced task controls testing.
* Provides functions for consult operations, transfer operations, and end consult actions.
* These utilities handle complex multi-agent scenarios and task state transitions.
*
* @packageDocumentation
*/
// Array to store captured console logs for verification
let capturedAdvancedLogs: string[] = [];
/**
* Sets up console logging to capture transfer and consult related callback logs.
* Captures transfer success, consult start/end success, and related SDK messages.
* @param page - The agent's main page
* @returns Function to remove the console handler
*/
export function setupAdvancedConsoleLogging(page: Page): () => void {
capturedAdvancedLogs.length = 0;
const consoleHandler = (msg) => {
const logText = msg.text();
if (
logText.includes('WXCC_SDK_TASK_TRANSFER_SUCCESS') ||
logText.includes('WXCC_SDK_TASK_CONSULT_START_SUCCESS') ||
logText.includes('WXCC_SDK_TASK_CONSULT_END_SUCCESS') ||
logText.includes('AgentConsultTransferred') ||
logText.includes('onEnd invoked') ||
logText.includes('onTransfer invoked') ||
logText.includes('onConsult invoked')
) {
capturedAdvancedLogs.push(logText);
}
};
page.on('console', consoleHandler);
return () => page.off('console', consoleHandler);
}
/**
* Clears the captured advanced logs array.
* Should be called before each test or verification to ensure clean state.
*/
export function clearAdvancedCapturedLogs(): void {
capturedAdvancedLogs.length = 0;
}
/**
* Verifies that transfer success logs are present.
* @throws Error if verification fails with detailed error message
*/
export function verifyTransferSuccessLogs(): void {
const transferLogs = capturedAdvancedLogs.filter((log) => log.includes('WXCC_SDK_TASK_TRANSFER_SUCCESS'));
if (transferLogs.length === 0) {
throw new Error(
`No 'WXCC_SDK_TASK_TRANSFER_SUCCESS' logs found. Captured logs: ${JSON.stringify(capturedAdvancedLogs)}`
);
}
}
/**
* Verifies that consult start success logs are present.
* @throws Error if verification fails with detailed error message
*/
export function verifyConsultStartSuccessLogs(): void {
const consultStartLogs = capturedAdvancedLogs.filter((log) => log.includes('WXCC_SDK_TASK_CONSULT_START_SUCCESS'));
if (consultStartLogs.length === 0) {
throw new Error(
`No 'WXCC_SDK_TASK_CONSULT_START_SUCCESS' logs found. Captured logs: ${JSON.stringify(capturedAdvancedLogs)}`
);
}
}
/**
* Verifies that consult end success logs are present.
* @throws Error if verification fails with detailed error message
*/
export function verifyConsultEndSuccessLogs(): void {
const consultEndLogs = capturedAdvancedLogs.filter((log) => log.includes('WXCC_SDK_TASK_CONSULT_END_SUCCESS'));
if (consultEndLogs.length === 0) {
throw new Error(
`No 'WXCC_SDK_TASK_CONSULT_END_SUCCESS' logs found. Captured logs: ${JSON.stringify(capturedAdvancedLogs)}`
);
}
}
/**
* Verifies that agent consult transferred logs are present (when consult is converted to transfer).
* @throws Error if verification fails with detailed error message
*/
export function verifyConsultTransferredLogs(): void {
const consultTransferredLogs = capturedAdvancedLogs.filter((log) => log.includes('AgentConsultTransferred'));
if (consultTransferredLogs.length === 0) {
throw new Error(`No 'AgentConsultTransferred' logs found. Captured logs: ${JSON.stringify(capturedAdvancedLogs)}`);
}
}
/**
* Unified function to handle consult and transfer actions for agent, queue, and dial number.
* @param page - The agent's main page
* @param type - 'agent' | 'queue' | 'dialNumber'
* @param action - 'consult' | 'transfer'
* @param value - agentName, queueName, or phoneNumber
* @returns Promise<void>
*/
export async function consultOrTransfer(
page: Page,
type: 'agent' | 'queue' | 'dialNumber',
action: 'consult' | 'transfer',
value: string
): Promise<void> {
// Determine which button to click for consult or transfer
if (action === 'consult') {
await page.getByTestId('call-control:consult').nth(1).click({timeout: AWAIT_TIMEOUT});
} else {
await page
.getByRole('group', {name: 'Call Control with Call'})
.getByLabel('Transfer Call')
.click({timeout: AWAIT_TIMEOUT});
}
// Navigate to the correct tab and perform the action
if (type === 'agent' || type === 'queue') {
const tabName = type === 'agent' ? 'Agents' : 'Queues';
await page.getByRole('tab', {name: tabName}).click({timeout: AWAIT_TIMEOUT});
const listItem = page.getByRole('listitem', {name: value, exact: true});
await listItem.waitFor({state: 'visible', timeout: AWAIT_TIMEOUT});
await listItem.scrollIntoViewIfNeeded();
await page.waitForTimeout(300);
const button = listItem.getByRole('button');
await button.waitFor({state: 'visible', timeout: AWAIT_TIMEOUT});
await button.scrollIntoViewIfNeeded();
await button.evaluate((el) => {
if (el.hasAttribute('disabled')) {
throw new Error(`${tabName.slice(0, -1)} button is disabled`);
}
});
let lastError;
for (let i = 0; i < 3; i++) {
try {
await button.click({timeout: AWAIT_TIMEOUT, force: true});
lastError = undefined;
break;
} catch (e) {
lastError = e;
await page.waitForTimeout(400);
}
}
if (lastError) {
throw lastError;
}
} else if (type === 'dialNumber') {
await page.getByRole('tab', {name: 'Dial Number'}).click({timeout: AWAIT_TIMEOUT});
const inputLocator = page.getByTestId('consult-transfer-dial-number-input').locator('input');
await inputLocator.waitFor({state: 'visible', timeout: AWAIT_TIMEOUT});
await inputLocator.click({timeout: AWAIT_TIMEOUT});
await inputLocator.fill(value, {timeout: AWAIT_TIMEOUT});
await page.getByTestId('dial-number-btn').click({timeout: AWAIT_TIMEOUT});
}
// Wait a moment for the action to be processed
await page.waitForTimeout(2000);
}
/**
* Cancels an ongoing consult and resumes the original call.
* @param page - The agent's main page
* @returns Promise<void>
*/
export async function cancelConsult(page: Page): Promise<void> {
// Click cancel consult button
await page.getByTestId('cancel-consult-btn').click({timeout: AWAIT_TIMEOUT});
}