testplane
Version:
Tests framework based on mocha and wdio
143 lines • 5.47 kB
JavaScript
import { WebDriverProtocol, MJsonWProtocol, JsonWProtocol, AppiumProtocol, ChromiumProtocol, SauceLabsProtocol, SeleniumProtocol, GeckoProtocol, WebDriverBidiProtocol, } from "@testplane/wdio-protocols";
import { webdriverMonad, sessionEnvironmentDetector, devtoolsEnvironmentDetector } from "@testplane/wdio-utils";
import { getEnvironmentVars } from "@testplane/webdriver";
import { SOCKET_MAX_TIMEOUT, SOCKET_TIMED_OUT_ERROR, MAX_ARGS_LENGTH } from "./constants.js";
import { BrowserEventNames } from "./types.js";
const SERVER_HANDLED_COMMANDS = ["debug", "saveScreenshot", "savePDF"];
const isElementRef = (data) => {
return (data !== null &&
typeof data === "object" &&
Object.keys(data).length === 1 &&
Object.keys(data)[0].startsWith("element-"));
};
const isProtocolCommand = (commandName) => {
return getAllProtocolCommands().includes(commandName) || SERVER_HANDLED_COMMANDS.includes(commandName);
};
export default class ProxyDriver {
static newSession(params, modifier, userPrototype, commandWrapper) {
const monad = webdriverMonad(params, modifier, getWdioPrototype(userPrototype));
const browser = monad(window.__testplane__.sessionId, commandWrapper);
window.__testplane__.customCommands.forEach(({ name, elementScope }) => {
browser.addCommand(name, mockCommand(name), elementScope);
});
return browser;
}
}
function getWdioPrototype(userPrototype) {
const prototype = {
...userPrototype,
...getMockedProtocolCommands(),
...getEnvironmentFlags(),
};
return prototype;
}
function getAllProtocolCommands() {
const protocols = [
WebDriverProtocol,
MJsonWProtocol,
JsonWProtocol,
AppiumProtocol,
ChromiumProtocol,
SauceLabsProtocol,
SeleniumProtocol,
GeckoProtocol,
WebDriverBidiProtocol,
];
const commands = new Set();
for (const protocol of protocols) {
for (const endpointData of Object.values(protocol)) {
for (const { command } of Object.values(endpointData)) {
commands.add(command);
}
}
}
return Array.from(commands);
}
function getMockedProtocolCommands() {
return [...getAllProtocolCommands(), ...SERVER_HANDLED_COMMANDS].reduce((acc, commandName) => {
acc[commandName] = { value: mockCommand(commandName) };
return acc;
}, {});
}
function mockCommand(commandName) {
return async function (...args) {
const { socket } = window.__testplane__;
const timeout = getCommandTimeout(commandName);
const element = isWdioElement(this) ? this : undefined;
try {
// TODO: remove type casting after https://github.com/socketio/socket.io/issues/4925
const [error, result] = (await socket
.timeout(timeout)
.emitWithAck(BrowserEventNames.runBrowserCommand, { name: commandName, args, element }));
if (error) {
throw error;
}
if (!isProtocolCommand(commandName)) {
if (isElementRef(result)) {
const browser = getBrowserInstance(this);
return browser.$(result);
}
if (Array.isArray(result) && result.length > 0 && result.every(isElementRef)) {
const browser = getBrowserInstance(this);
return Promise.all(result.map(item => browser.$(item)));
}
}
return result;
}
catch (err) {
let error = err;
if (error.message === SOCKET_TIMED_OUT_ERROR) {
error = new Error(`Didn't receive response from worker when executing browser command "${commandName}" with arguments "[${normalizeCommandArgs(commandName, args)}]" in ${timeout}ms`);
}
throw error;
}
};
}
function getEnvironmentFlags() {
const { capabilities, requestedCapabilities, config } = window.__testplane__;
const environment = config.automationProtocol === "devtools"
? devtoolsEnvironmentDetector(capabilities)
: sessionEnvironmentDetector({
capabilities,
requestedCapabilities: requestedCapabilities,
});
return getEnvironmentVars(environment);
}
function getCommandTimeout(commandName) {
const { config } = window.__testplane__;
let timeout = config.httpTimeout;
if (commandName === "debug" || commandName === "switchToRepl") {
timeout = SOCKET_MAX_TIMEOUT;
}
if (commandName === "navigateTo" && config.urlHttpTimeout) {
timeout = config.urlHttpTimeout;
}
return timeout;
}
function normalizeCommandArgs(name, args = []) {
if (name === "execute") {
return ["code"];
}
return args.map(arg => {
if (typeof arg === "string") {
return truncate(arg, MAX_ARGS_LENGTH);
}
if (arg !== null && typeof arg === "object") {
return "obj";
}
return arg;
});
}
function truncate(value, maxLen) {
if (value.length <= maxLen) {
return value;
}
return `${value.slice(0, maxLen - 3)}...`;
}
function isWdioElement(ctx) {
return Boolean(ctx.elementId);
}
function getBrowserInstance(ctx) {
return isWdioElement(ctx) && ctx.parent ? getBrowserInstance(ctx.parent) : ctx;
}
//# sourceMappingURL=driver.js.map