UNPKG

testplane

Version:

Tests framework based on mocha and wdio

155 lines 6.66 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = __importDefault(require("lodash")); const emptyPageUrl = "about:blank"; const is = { image: match => match.headers?.Accept?.includes("image"), stylesheet: match => match.headers?.Accept?.includes("text/css"), font: match => lodash_1.default.isString(match.url) && [".ttf", ".woff", ".woff2"].some(ext => match.url.endsWith(ext)), favicon: match => lodash_1.default.isString(match.url) && match.url.endsWith("/favicon.ico"), }; const makeOpenAndWaitCommand = (config, session) => async function openAndWait(uri, { selector = [], predicate, waitNetworkIdle = config.openAndWaitOpts?.waitNetworkIdle, waitNetworkIdleTimeout = config.openAndWaitOpts?.waitNetworkIdleTimeout, failOnNetworkError = config.openAndWaitOpts?.failOnNetworkError, shouldThrowError = shouldThrowErrorDefault, ignoreNetworkErrorsPatterns = config.openAndWaitOpts?.ignoreNetworkErrorsPatterns, timeout = config.openAndWaitOpts?.timeout || config?.pageLoadTimeout || 0, } = {}) { const PageLoader = await Promise.resolve().then(() => __importStar(require("../../utils/page-loader"))).then(m => m.default); const isChrome = config.desiredCapabilities?.browserName === "chrome"; const isCDP = config.automationProtocol === "devtools"; waitNetworkIdle &&= isChrome || isCDP; const originalPageLoadTimeout = config.pageLoadTimeout; const shouldUpdateTimeout = timeout && timeout !== originalPageLoadTimeout; const setPageLoadTimeout = async (value) => { if (!value) { return; } try { await session.setTimeout({ pageLoad: value }); } catch { /* */ } }; const restorePageLoadTimeout = () => { if (shouldUpdateTimeout && originalPageLoadTimeout) { // No await because session might be stuck on url() command setPageLoadTimeout(originalPageLoadTimeout).catch(() => { }); } }; if (!uri || uri === emptyPageUrl) { return new Promise(resolve => { session.url(uri).then(() => resolve()); }); } const selectors = typeof selector === "string" ? [selector] : selector; const pageLoader = new PageLoader(session, { selectors, predicate, timeout, waitNetworkIdle, waitNetworkIdleTimeout, }); let selectorsResolved = !selectors.length; let predicateResolved = !predicate; let networkResolved = !waitNetworkIdle; if (shouldUpdateTimeout) { await setPageLoadTimeout(timeout); } // Create hard timeout promise to guarantee timeout is respected // This is needed because WebDriver pageLoad timeout only affects the browser's // page load event, not the HTTP connection/response time let hardTimeoutId; const hardTimeoutPromise = timeout ? new Promise((_, reject) => { hardTimeoutId = setTimeout(() => { reject(new Error(`openAndWait timed out after ${timeout}ms`)); }, timeout); }) : null; const loadPromise = new Promise((resolve, reject) => { const handleError = (err) => { reject(new Error(`url: ${err.message}`)); }; const checkLoaded = () => { if (selectorsResolved && predicateResolved && networkResolved) { resolve(); } }; const goToPage = async () => { await session.url(uri, { timeout }); }; pageLoader.on("pageLoadError", handleError); pageLoader.on("selectorsError", handleError); pageLoader.on("predicateError", handleError); pageLoader.on("networkError", match => { if (!failOnNetworkError) { return; } const shouldIgnore = isMatchPatterns(ignoreNetworkErrorsPatterns, match.url); if (!shouldIgnore && shouldThrowError(match)) { reject(new Error(`url: couldn't get content from ${match.url}: ${match.statusCode}`)); } }); pageLoader.on("selectorsExist", () => { selectorsResolved = true; checkLoaded(); }); pageLoader.on("predicateResolved", () => { predicateResolved = true; checkLoaded(); }); pageLoader.on("networkResolved", () => { networkResolved = true; checkLoaded(); }); pageLoader.load(goToPage).then(checkLoaded); }); const racePromises = [loadPromise]; if (hardTimeoutPromise) { racePromises.push(hardTimeoutPromise); } return Promise.race(racePromises).finally(() => { if (hardTimeoutId) { clearTimeout(hardTimeoutId); } // No await, because session might be stuck on url() command pageLoader.unsubscribe(); restorePageLoadTimeout(); }); }; exports.default = (browser) => { const { publicAPI: session, config } = browser; session.addCommand("openAndWait", makeOpenAndWaitCommand(config, session)); }; function isMatchPatterns(patterns = [], str) { return patterns.some(pattern => (lodash_1.default.isString(pattern) ? str.includes(pattern) : pattern.exec(str))); } function shouldThrowErrorDefault(match) { if (is.favicon(match)) { return false; } return is.image(match) || is.stylesheet(match) || is.font(match); } //# sourceMappingURL=openAndWait.js.map