testplane
Version:
Tests framework based on mocha and wdio
155 lines • 6.66 kB
JavaScript
;
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