Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions playwright/Utils/helperUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Parses a time string in MM:SS format and converts it to total seconds
* @param timeString - Time string in format "MM:SS" (e.g., "01:30" for 1 minute 30 seconds)
* @returns Total number of seconds
* @example
* ```typescript
* parseTimeString("01:30"); // Returns 90 (1 minute 30 seconds)
* parseTimeString("00:45"); // Returns 45 (45 seconds)
* parseTimeString("10:00"); // Returns 600 (10 minutes)
* ```
*/
export function parseTimeString(timeString: string): number {
const parts = timeString.split(':');
const minutes = parseInt(parts[0], 10) || 0;
const seconds = parseInt(parts[1], 10) || 0;
return minutes * 60 + seconds;
}

/**
* Waits for WebSocket disconnection by monitoring console messages for specific disconnection indicators
* @param consoleMessages - Array of console messages to monitor
* @param timeoutMs - Maximum time to wait for disconnection in milliseconds (default: 15000)
* @returns Promise<boolean> - True if disconnection is detected, false if timeout is reached
* @description Monitors for network disconnection messages or WebSocket offline status changes
* @example
* ```typescript
* consoleMessages.length = 0; // Clear existing messages
* await page.context().setOffline(true);
* const isDisconnected = await waitForWebSocketDisconnection(consoleMessages);
* expect(isDisconnected).toBe(true);
* ```
*/
export async function waitForWebSocketDisconnection(consoleMessages: string[], timeoutMs: number = 15000): Promise<boolean> {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
const webSocketDisconnectLog = consoleMessages.find(
(msg) =>
msg.includes('Failed to load resource: net::ERR_INTERNET_DISCONNECTED') ||
msg.includes('[WebSocketStatus] event=checkOnlineStatus | online status= false')
);
if (webSocketDisconnectLog) {
return true;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
return false;
}

/**
* Waits for WebSocket reconnection by monitoring console messages for online status changes
* @param consoleMessages - Array of console messages to monitor
* @param timeoutMs - Maximum time to wait for reconnection in milliseconds (default: 15000)
* @returns Promise<boolean> - True if reconnection is detected, false if timeout is reached
* @description Monitors for WebSocket online status change messages indicating successful reconnection
* @example
* ```typescript
* consoleMessages.length = 0; // Clear existing messages
* await page.context().setOffline(false);
* const isReconnected = await waitForWebSocketReconnection(consoleMessages);
* expect(isReconnected).toBe(true);
* ```
*/
export async function waitForWebSocketReconnection(consoleMessages: string[], timeoutMs: number = 15000): Promise<boolean> {
const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) {
const webSocketReconnectLog = consoleMessages.find((msg) =>
msg.includes('[WebSocketStatus] event=checkOnlineStatus | online status= true')
);
if (webSocketReconnectLog) {
return true;
}
await new Promise((resolve) => setTimeout(resolve, 100));
}
return false;
}
19 changes: 16 additions & 3 deletions playwright/Utils/initUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ export const disableMultiLogin = async (page: Page): Promise<void> => {
/**
* Initializes the widgets by clicking the init widgets button and waiting for station-login widget to be visible
* @param page - The Playwright page object
* @description The station-login widget should be checked/enabled before using this function
* @throws {Error} When station-login widget is not visible after initialization
* @description The station-login widget should be checked/enabled before using this function.
* If the widget is not visible after 50 seconds, retries once more with another 50-second timeout.
* @throws {Error} When station-login widget is not visible after two initialization attempts (100 seconds total)
* @example
* ```typescript
* // Ensure station-login widget is checked first
Expand All @@ -136,7 +137,19 @@ export const disableMultiLogin = async (page: Page): Promise<void> => {
export const initialiseWidgets = async (page: Page): Promise<void> => {
await page.getByTestId('samples:init-widgets-button').click();

await page.getByTestId('station-login-widget').waitFor({state: 'visible', timeout: 50000});
try {
await page.getByTestId('station-login-widget').waitFor({state: 'visible', timeout: 50000});
} catch (error) {
// First attempt failed, try clicking init widgets button again
await page.getByTestId('samples:init-widgets-button').click();

try {
await page.getByTestId('station-login-widget').waitFor({state: 'visible', timeout: 50000});
} catch (secondError) {
// Second attempt also failed, throw error
throw new Error('Station login widget failed to become visible after two initialization attempts (100 seconds total)');
}
}
};
Comment thread
rarajes2 marked this conversation as resolved.

/**
Expand Down
45 changes: 43 additions & 2 deletions playwright/Utils/stationLoginUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Page, expect} from '@playwright/test';
import dotenv from 'dotenv';
import {LOGIN_MODE} from '../constants';
import {LOGIN_MODE, LONG_WAIT} from '../constants';

dotenv.config();

Expand Down Expand Up @@ -153,4 +153,45 @@ export const telephonyLogin = async (page: Page, mode: string, number?: string):
} else {
throw new Error(`Unsupported login mode: ${mode}. Use one of: ${Object.values(LOGIN_MODE).join(', ')}`);
}
};
}

/**
* Verifies that the login mode selector displays the expected login mode
* @param page - The Playwright page object
* @param expectedMode - The expected login mode text to verify (e.g., 'Dial Number', 'Extension', 'Desktop')
* @description Checks the login option select element's trigger text to ensure it matches the expected mode
* @throws {Error} When the login mode doesn't match the expected value
* @example
* ```typescript
* await verifyLoginMode(page, LOGIN_MODE.DIAL_NUMBER);
* await verifyLoginMode(page, LOGIN_MODE.EXTENSION);
* await verifyLoginMode(page, LOGIN_MODE.DESKTOP);
* ```
*/
export async function verifyLoginMode(page: Page, expectedMode: string): Promise<void> {
await expect(page.getByTestId('login-option-select').locator('#select-base-triggerid')).toContainText(expectedMode);
}

/**
* Ensures the user state widget is visible by checking its current state and logging in if necessary
* @param page - The Playwright page object
* @param loginMode - The login mode to use if login is required (from LOGIN_MODE constants)
* @description Checks if the state-select widget is visible; if not, performs telephony login and waits for it to appear
* @throws {Error} When telephony login fails or state widget doesn't become visible
* @example
* ```typescript
* await ensureUserStateVisible(page, LOGIN_MODE.DIAL_NUMBER);
* await ensureUserStateVisible(page, LOGIN_MODE.EXTENSION);
* await ensureUserStateVisible(page, LOGIN_MODE.DESKTOP);
* ```
*/
export async function ensureUserStateVisible(page: Page, loginMode: string): Promise<void> {
const isUserStateWidgetVisible = await page
.getByTestId('state-select')
.isVisible()
.catch(() => false);
if (!isUserStateWidgetVisible) {
await telephonyLogin(page, loginMode);
await expect(page.getByTestId('state-select')).toBeVisible({timeout: LONG_WAIT});
}
}
3 changes: 0 additions & 3 deletions playwright/global.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import {test as setup} from '@playwright/test';
import {oauthLogin} from './Utils/initUtils';
const fs = require('fs');
const path = require('path');
import dotenv from 'dotenv';

dotenv.config();

setup('OAuth', async ({browser}) => {
const agentId = 'AGENT1'; // Configure which agent to set up
Expand Down
2 changes: 0 additions & 2 deletions playwright/login-user-state.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {test, expect} from '@playwright/test';
import fs from 'fs';
import dotenv from 'dotenv';

dotenv.config();
test.describe('Login and User State tests', async () => {
test('Login: should login using Extension login option', async ({page}) => {
await page.goto('http://localhost:3000/');
Expand Down
Loading
Loading