UNPKG

@tshifhiwa/ohrm-ui-automation-framework

Version:

Playwright and TypeScript–based test automation framework for validating core UI features and workflows of the OrangeHRM demo application.

515 lines (490 loc) 18.9 kB
import type { Page, Frame, Locator, FrameLocator } from "@playwright/test"; import { ActionBase } from "./actionBase.js"; import { ElementActions } from "./elementActions.js"; import { ElementAssertions } from "./elementAssertions.js"; export class FrameActions extends ActionBase { private elementActions: ElementActions; private elementAssertions: ElementAssertions; constructor(page: Page, elementActions: ElementActions, elementAssertions: ElementAssertions) { super(page); this.elementActions = elementActions; this.elementAssertions = elementAssertions; } /** * Retrieves a frame by its name. * @param frameName The name attribute of the frame. * @param callerMethodName The name of the method that called the action. * @returns A promise that resolves with the frame if found, or null if not found. */ public async getFrameByName(frameName: string, callerMethodName: string): Promise<Frame | null> { return this.performAction( () => Promise.resolve(this.page.frame({ name: frameName })), callerMethodName, `Retrieved frame: ${frameName}`, `Failed to get frame: ${frameName}`, ); } /** * Retrieves a frame by its URL. * @param frameUrl The URL of the frame (can be a string or regex). * @param callerMethodName The name of the method that called the action. * @returns A promise that resolves with the frame if found, or null if not found. */ public async getFrameByUrl( frameUrl: string | RegExp, callerMethodName: string, ): Promise<Frame | null> { return this.performAction( () => Promise.resolve(this.page.frame({ url: frameUrl })), callerMethodName, `Retrieved frame by URL: ${frameUrl}`, `Failed to get frame by URL: ${frameUrl}`, ); } /** * Retrieves a FrameLocator by its name. * @param frameName The name attribute of the frame. * @param callerMethodName The name of the method that called the action. * @returns A FrameLocator for the specified frame. */ public async getFrameLocator(frameName: string, callerMethodName: string): Promise<FrameLocator> { return this.performAction( () => Promise.resolve(this.page.frameLocator(`[name="${frameName}"]`)), callerMethodName, `Retrieved frame locator: ${frameName}`, `Failed to get frame locator: ${frameName}`, ); } /** * Retrieves all frames on the page. * @param callerMethodName The name of the method that called the action. * @returns A promise that resolves with an array of all frames. */ public async getAllFrames(callerMethodName: string): Promise<Frame[]> { return this.performAction( () => Promise.resolve(this.page.frames()), callerMethodName, "Retrieved all frames", "Failed to get all frames", ); } /** * Waits for a frame to be available. * @param frameName The name attribute of the frame. * @param callerMethodName The name of the method that called the action. * @param timeout Optional timeout in milliseconds. * @returns A promise that resolves with the frame when available. */ public async waitForFrame( frameName: string, callerMethodName: string, timeout?: number, ): Promise<Frame> { return this.performAction( async () => { const startTime = Date.now(); const maxTimeout = timeout || 30000; while (Date.now() - startTime < maxTimeout) { const frame = this.page.frame({ name: frameName }); if (frame) return frame; await this.page.waitForTimeout(100); } throw new Error(`Frame '${frameName}' not found within timeout`); }, callerMethodName, `Frame '${frameName}' is available`, `Failed to wait for frame: ${frameName}`, ); } /** * Switches to a frame and returns its context. * @param frameName The name attribute of the frame. * @param callerMethodName The name of the method that called the action. * @returns A promise that resolves with the frame context. */ public async switchToFrame(frameName: string, callerMethodName: string): Promise<Frame> { return this.performAction( async () => { const frame = await this.getFrameByName(frameName, callerMethodName); if (!frame) throw new Error(`Frame '${frameName}' not found`); return frame; }, callerMethodName, `Switched to frame: ${frameName}`, `Failed to switch to frame: ${frameName}`, ); } /** * Gets a locator for an element within a specific frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @returns A promise that resolves with the element locator. */ public async getElementInFrame( frameName: string, selector: string, callerMethodName: string, ): Promise<Locator> { return this.performAction( async () => { const frame = await this.getFrameByName(frameName, callerMethodName); if (!frame) throw new Error(`Frame '${frameName}' not found`); return frame.locator(selector); }, callerMethodName, `Retrieved element '${selector}' in frame '${frameName}'`, `Failed to get element '${selector}' in frame '${frameName}'`, ); } /** * Clicks an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @param options Optional click options. */ public async clickElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, options?: { force?: boolean }, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.clickElement(element, callerMethodName, elementName, options); }, callerMethodName, `Clicked ${elementName || "element"} in frame ${frameName}`, `Failed to click ${elementName || "element"} in frame ${frameName}`, ); } /** * Fills an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param value The value to fill. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @param options Optional fill options. */ public async fillElementInFrame( frameName: string, selector: string, value: string, callerMethodName: string, elementName?: string, options?: { force?: boolean }, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.fillElement( element, value, callerMethodName, elementName, options, ); }, callerMethodName, `Filled ${elementName || "element"} in frame ${frameName}`, `Failed to fill ${elementName || "element"} in frame ${frameName}`, ); } /** * Checks a checkbox or radio button within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async checkElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.checkElement(element, callerMethodName, elementName); }, callerMethodName, `Checked ${elementName || "element"} in frame ${frameName}`, `Failed to check ${elementName || "element"} in frame ${frameName}`, ); } /** * Unchecks a checkbox within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async uncheckElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.uncheckElement(element, callerMethodName, elementName); }, callerMethodName, `Unchecked ${elementName || "element"} in frame ${frameName}`, `Failed to uncheck ${elementName || "element"} in frame ${frameName}`, ); } /** * Selects an option from a dropdown within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param optionValue The value of the option to select. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async selectOptionInFrame( frameName: string, selector: string, optionValue: string, callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.selectOption(element, callerMethodName, optionValue, elementName); }, callerMethodName, `Selected option in ${elementName || "element"} in frame ${frameName}`, `Failed to select option in ${elementName || "element"} in frame ${frameName}`, ); } /** * Hovers over an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async hoverElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.hoverElement(element, callerMethodName, elementName); }, callerMethodName, `Hovered over ${elementName || "element"} in frame ${frameName}`, `Failed to hover over ${elementName || "element"} in frame ${frameName}`, ); } /** * Double-clicks an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @param options Optional double-click options. */ public async doubleClickElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, options?: { force?: boolean }, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.doubleClickElement( element, callerMethodName, elementName, options, ); }, callerMethodName, `Double-clicked ${elementName || "element"} in frame ${frameName}`, `Failed to double-click ${elementName || "element"} in frame ${frameName}`, ); } /** * Right-clicks an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @param options Optional right-click options. */ public async rightClickElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, options?: { force?: boolean }, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementActions.rightClickElement( element, callerMethodName, elementName, options, ); }, callerMethodName, `Right-clicked ${elementName || "element"} in frame ${frameName}`, `Failed to right-click ${elementName || "element"} in frame ${frameName}`, ); } /** * Gets text content from an element within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @returns A promise that resolves with the text content. */ public async getTextFromFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<string | null> { return this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); return this.elementAssertions.getElementProperty<string>( element, callerMethodName, "textContent", undefined, elementName, ); }, callerMethodName, `Retrieved text from ${elementName || "element"} in frame ${frameName}`, `Failed to get text from ${elementName || "element"} in frame ${frameName}`, ); } /** * Verifies element state within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param state The expected state. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async verifyElementStateInFrame( frameName: string, selector: string, state: "enabled" | "disabled" | "visible" | "hidden", callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementAssertions.verifyElementState( element, callerMethodName, state, elementName, ); }, callerMethodName, `Verified ${elementName || "element"} is ${state} in frame ${frameName}`, `Failed to verify ${elementName || "element"} is ${state} in frame ${frameName}`, ); } /** * Waits for an element to be visible within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. */ public async waitForElementInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<void> { await this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); await this.elementAssertions.waitForElementState( element, callerMethodName, "visible", elementName, ); }, callerMethodName, `${elementName || "element"} is visible in frame ${frameName}`, `Failed to wait for ${elementName || "element"} in frame ${frameName}`, ); } /** * Checks if an element is visible within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the element. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the element. * @returns A promise that resolves with true if visible, false otherwise. */ public async isElementVisibleInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<boolean> { return this.performAction( async () => { const element = await this.getElementInFrame(frameName, selector, callerMethodName); return this.elementAssertions.isElementVisible(element, callerMethodName, elementName); }, callerMethodName, `Checked visibility of ${elementName || "element"} in frame ${frameName}`, `Failed to check visibility of ${elementName || "element"} in frame ${frameName}`, ); } /** * Gets the count of elements matching a selector within a frame. * @param frameName The name attribute of the frame. * @param selector The CSS selector for the elements. * @param callerMethodName The name of the method that called the action. * @param elementName Optional name of the elements. * @returns A promise that resolves with the count. */ public async getElementCountInFrame( frameName: string, selector: string, callerMethodName: string, elementName?: string, ): Promise<number> { return this.performAction( async () => { const frame = await this.getFrameByName(frameName, callerMethodName); if (!frame) throw new Error(`Frame '${frameName}' not found`); const elements = frame.locator(selector); return this.elementAssertions.getElementCount(elements, callerMethodName, elementName); }, callerMethodName, `Retrieved count of ${elementName || "elements"} in frame ${frameName}`, `Failed to get count of ${elementName || "elements"} in frame ${frameName}`, ); } }