UNPKG

electron-playwright-helpers

Version:

Helper functions for Electron end-to-end testing using Playwright

215 lines 8.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getWindowByUrl = getWindowByUrl; exports.getWindowByTitle = getWindowByTitle; exports.getWindowByMatcher = getWindowByMatcher; exports.waitForWindowByUrl = waitForWindowByUrl; exports.waitForWindowByTitle = waitForWindowByTitle; exports.waitForWindowByMatcher = waitForWindowByMatcher; const utilities_1 = require("./utilities"); /** * Helper to match a string against a pattern (string or RegExp). * For strings, performs a substring match (includes). * For RegExp, tests the pattern against the value. */ function matchesPattern(value, pattern) { if (pattern instanceof RegExp) { return pattern.test(value); } return value.includes(pattern); } async function getWindowByUrl(electronApp, pattern, options) { return getWindowByMatcher(electronApp, async (page) => { const url = page.url(); if (!url) { try { await page.waitForURL((u) => !!u, { timeout: 1000 }); } catch { return false; } } return matchesPattern(page.url(), pattern); }, options); } async function getWindowByTitle(electronApp, pattern, options) { return getWindowByMatcher(electronApp, async (page) => { const title = await page.title(); return matchesPattern(title, pattern); }, options); } async function getWindowByMatcher(electronApp, matcher, options) { const { all, ...retryOpts } = options || {}; const findWindows = async () => { const windows = electronApp.windows(); if (all) { const results = []; for (const page of windows) { if (await matcher(page)) { results.push(page); } } return results; } // Return first match for (const page of windows) { if (await matcher(page)) { return page; } } return undefined; }; return (0, utilities_1.retry)(findWindows, retryOpts); } // ============================================================================ // waitForWindowByUrl // ============================================================================ /** * Wait for a window whose URL matches the given pattern. * * This function checks existing windows first, then listens for new windows. * It uses polling to handle windows that may have their URL change after opening. * * @category Window Helpers * * @param electronApp - The Playwright ElectronApplication * @param pattern - A string (substring match) or RegExp to match against the URL * @param options - Optional timeout and interval settings * @returns The matching Page * @throws Error if timeout is reached before a matching window is found * * @example * ```ts * // Click something that opens a new window, then wait for it * await page.click('#open-settings') * const settingsWindow = await waitForWindowByUrl(app, '/settings', { timeout: 5000 }) * ``` */ async function waitForWindowByUrl(electronApp, pattern, options) { return waitForWindowByMatcher(electronApp, async (page) => { const url = page.url(); if (!url) { try { await page.waitForURL((u) => !!u, { timeout: 1000 }); } catch { return false; } } return matchesPattern(page.url(), pattern); }, options); } // ============================================================================ // waitForWindowByTitle // ============================================================================ /** * Wait for a window whose title matches the given pattern. * * This function checks existing windows first, then listens for new windows. * It uses polling to handle windows that may have their title change after opening. * * @category Window Helpers * * @param electronApp - The Playwright ElectronApplication * @param pattern - A string (substring match) or RegExp to match against the title * @param options - Optional timeout and interval settings * @returns The matching Page * @throws Error if timeout is reached before a matching window is found * * @example * ```ts * // Wait for a window with a specific title to appear * const prefsWindow = await waitForWindowByTitle(app, 'Preferences', { timeout: 5000 }) * ``` */ async function waitForWindowByTitle(electronApp, pattern, options) { return waitForWindowByMatcher(electronApp, async (page) => { const title = await page.title(); return matchesPattern(title, pattern); }, options); } // ============================================================================ // waitForWindowByMatcher // ============================================================================ /** * Wait for a window that matches the provided matcher function. * * This function: * 1. Checks existing windows first * 2. Listens for new window events * 3. Polls existing windows periodically (to catch URL/title changes) * * @category Window Helpers * * @param electronApp - The Playwright ElectronApplication * @param matcher - A function that receives a Page and returns true if it matches * @param options - Optional timeout and interval settings * @returns The matching Page * @throws Error if timeout is reached before a matching window is found * * @example * ```ts * const window = await waitForWindowByMatcher(app, async (page) => { * const title = await page.title() * return title.startsWith('Document:') * }, { timeout: 10000 }) * ``` */ async function waitForWindowByMatcher(electronApp, matcher, options) { var _a, _b; const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 10000; const interval = (_b = options === null || options === void 0 ? void 0 : options.interval) !== null && _b !== void 0 ? _b : 200; // Check existing windows first const windows = electronApp.windows(); for (const page of windows) { if (await matcher(page)) { return page; } } // Track the polling interval so we can clean it up let pollIntervalId; // Race between: // 1. waitForEvent('window') with predicate for new windows // 2. Polling existing windows for changes (URL/title may change after load) try { return await Promise.race([ // Wait for new window that matches electronApp.waitForEvent('window', { timeout, predicate: matcher, }), // Poll existing windows new Promise((resolve, reject) => { const startTime = Date.now(); pollIntervalId = setInterval(async () => { try { if (Date.now() - startTime > timeout) { clearInterval(pollIntervalId); reject(new Error(`Timeout waiting for window matching criteria after ${timeout}ms`)); return; } const windows = electronApp.windows(); for (const page of windows) { if (await matcher(page)) { clearInterval(pollIntervalId); resolve(page); return; } } } catch (error) { clearInterval(pollIntervalId); reject(error); } }, interval); }), ]); } finally { // Clean up the polling interval when the race completes if (pollIntervalId !== undefined) { clearInterval(pollIntervalId); } } } //# sourceMappingURL=window_helpers.js.map