141 lines
4.9 KiB
TypeScript
141 lines
4.9 KiB
TypeScript
import { Page, Locator, FrameLocator } from '@playwright/test';
|
|
import { expect } from '@playwright/test';
|
|
|
|
/**
|
|
* Gets a FrameLocator for an iframe inside a Shadow DOM
|
|
* @param page - Playwright page object
|
|
* @param componentSelector - Selector for the web component with Shadow DOM
|
|
* @param iframeSelector - Selector for the iframe within the Shadow DOM
|
|
* @returns FrameLocator that can be used to access iframe contents
|
|
*/
|
|
export async function getIframeInShadowDom(
|
|
page: Page,
|
|
componentSelector: string = 'openvidu-meet',
|
|
iframeSelector: string = 'iframe'
|
|
): Promise<FrameLocator> {
|
|
// Verify the component exists
|
|
await page.waitForSelector(componentSelector);
|
|
|
|
// Use frameLocator to access the iframe contents
|
|
return page.frameLocator(`${componentSelector} >>> ${iframeSelector}`);
|
|
}
|
|
|
|
/**
|
|
* Waits for an element inside an iframe within Shadow DOM
|
|
* @param page - Playwright page object
|
|
* @param elementSelector - Selector for the element inside the iframe
|
|
* @param options - Optional configuration
|
|
* @returns Locator for the found element
|
|
*/
|
|
export async function waitForElementInIframe(
|
|
page: Page,
|
|
elementSelector: string,
|
|
options: {
|
|
componentSelector?: string;
|
|
iframeSelector?: string;
|
|
timeout?: number;
|
|
state?: 'attached' | 'detached' | 'visible' | 'hidden';
|
|
} = {}
|
|
): Promise<Locator> {
|
|
const {
|
|
componentSelector = 'openvidu-meet',
|
|
iframeSelector = 'iframe',
|
|
timeout = 30000,
|
|
state = 'visible'
|
|
} = options;
|
|
|
|
// Get the iframe
|
|
const frameLocator = await getIframeInShadowDom(page, componentSelector, iframeSelector);
|
|
|
|
// Get element locator
|
|
const elementLocator = frameLocator.locator(elementSelector);
|
|
|
|
// Wait for the element with the specified state
|
|
await elementLocator.waitFor({ state, timeout });
|
|
|
|
return elementLocator;
|
|
}
|
|
|
|
// Interacti with an element inside an iframe within Shadow DOM
|
|
export async function interactWithElementInIframe(
|
|
page: Page,
|
|
elementSelector: string,
|
|
options: {
|
|
action: 'click' | 'fill' | 'type';
|
|
value?: string; // Only needed for 'fill' or 'type' actions
|
|
timeout?: number;
|
|
} = {
|
|
action: 'click',
|
|
value: '',
|
|
timeout: 30000
|
|
}
|
|
): Promise<void> {
|
|
const { action, value = '', timeout = 30000 } = options;
|
|
const element = await waitForElementInIframe(page, elementSelector);
|
|
// Perform the specified action
|
|
switch (action) {
|
|
case 'click':
|
|
await element.click();
|
|
break;
|
|
case 'fill':
|
|
await element.fill(value);
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported action: ${action}`);
|
|
}
|
|
}
|
|
|
|
export const prepareForJoiningRoom = async (page: Page, url: string, roomPrefix: string) => {
|
|
await page.goto(url);
|
|
await page.waitForSelector('.rooms-container');
|
|
await page.waitForSelector(`#${roomPrefix}`);
|
|
await page.click('.dropdown-button');
|
|
await page.waitForSelector('#join-as-moderator');
|
|
await page.waitForSelector('#join-as-publisher');
|
|
};
|
|
|
|
export const joinRoomAs = async (role: 'moderator' | 'publisher', page: Page) => {
|
|
await page.click('#join-as-' + role);
|
|
const component = page.locator('openvidu-meet');
|
|
await expect(component).toBeVisible();
|
|
};
|
|
|
|
export const leaveRoom = async (page: Page) => {
|
|
const button = await waitForElementInIframe(page, '#leave-btn');
|
|
await button.click();
|
|
await page.waitForSelector('.event-LEFT');
|
|
};
|
|
|
|
export const startScreenSharing = async (page: Page) => {
|
|
await interactWithElementInIframe(page, '#screenshare-btn', { action: 'click' });
|
|
await waitForElementInIframe(page, '#local-element-screen_share', { state: 'visible' });
|
|
};
|
|
|
|
export const stopScreenSharing = async (page: Page) => {
|
|
await interactWithElementInIframe(page, '#screenshare-btn', { action: 'click' });
|
|
await page.waitForTimeout(200); // Wait for screen menu
|
|
await interactWithElementInIframe(page, '#disable-screen-button', { action: 'click' });
|
|
await page.waitForTimeout(500); // Wait for screen to stop sharing
|
|
};
|
|
|
|
export const applyVirtualBackground = async (page: Page, backgroundId: string) => {
|
|
await interactWithElementInIframe(page, '#more-options-btn', { action: 'click' });
|
|
await page.waitForTimeout(500);
|
|
await interactWithElementInIframe(page, '#virtual-bg-btn', { action: 'click' });
|
|
await waitForElementInIframe(page, 'ov-background-effects-panel', { state: 'visible' });
|
|
await interactWithElementInIframe(page, `#effect-${backgroundId}`, { action: 'click' });
|
|
await interactWithElementInIframe(page, '.panel-close-button', { action: 'click' });
|
|
};
|
|
|
|
export const removeVirtualBackground = async (page: Page) => {
|
|
await interactWithElementInIframe(page, '#more-options-btn', { action: 'click' });
|
|
await page.waitForTimeout(500);
|
|
await interactWithElementInIframe(page, '#virtual-bg-btn', { action: 'click' });
|
|
await interactWithElementInIframe(page, '#no_effect-btn', { action: 'click' });
|
|
await page.waitForTimeout(500); // Wait for background to be removed
|
|
};
|
|
export const saveScreenshot = async (page: Page, filename: string, selector: string) => {
|
|
const element = await waitForElementInIframe(page, selector);
|
|
await element.screenshot({ path: filename });
|
|
};
|