UNPKG

@wdio/browser-runner

Version:
324 lines (317 loc) 18.2 kB
var __typeError = (msg) => { throw TypeError(msg); }; var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); // src/browser/setup.ts import { automationProtocolPath } from "virtual:wdio"; import { expect } from "expect-webdriverio"; import { remote } from "webdriverio"; import { _setGlobal } from "@wdio/globals"; // src/browser/frameworks/mocha.ts import safeStringify from "safe-stringify"; import { setupEnv, formatMessage } from "@wdio/mocha-framework/common"; import { MESSAGE_TYPES } from "@wdio/types"; // src/browser/utils.ts function getCID() { var _a; const urlParamString = new URLSearchParams(window.location.search); const cid = ( // initial request contains cid as query parameter urlParamString.get("cid") || // if not provided check for document cookie, set by `@wdio/runner` package ((_a = (document.cookie.split(";") || []).find((c) => c.includes("WDIO_CID"))) == null ? void 0 : _a.trim().split("=").pop()) ); if (!cid) { throw new Error('"cid" query parameter is missing'); } return cid; } var showPopupWarning = (name, value, defaultValue) => (...params) => { const formatedParams = params.map((p) => JSON.stringify(p)).join(", "); console.warn("WebdriverIO encountered a `".concat(name, "(").concat(formatedParams, ")` call that it cannot handle by default, so it returned `").concat(value, "`. Read more in https://webdriver.io/docs/runner#limitations.\n If needed, mock the `").concat(name, '` call manually like:\n ```\n import { spyOn } from "@wdio/browser-runner"\n spyOn(window, "').concat(name, '")').concat(defaultValue ? ".mockReturnValue(".concat(JSON.stringify(defaultValue), ")") : "", "\n ").concat(name, "(").concat(formatedParams, ")\n expect(").concat(name, ").toHaveBeenCalledWith(").concat(formatedParams, ")\n ```")); return value; }; var pick = (keys, obj) => { return Object.fromEntries( Object.entries(obj).filter(([k]) => keys.includes(k)) ); }; var RELEVANT_TEST_PROPS = ["type", "title", "body", "async", "sync", "timedOut", "pending", "parent", "test"]; function filterTestArgument(arg, file) { if (!arg) { return arg; } const newArgs = pick(RELEVANT_TEST_PROPS, arg); return { ...newArgs, file: arg.file || file, test: filterTestArgument(newArgs.test, file), parent: filterTestArgument(newArgs.parent, file) }; } // src/constants.ts var WDIO_EVENT_NAME = "wdio:workerMessage"; var EVENTS = { "suite": "suite:start", "suite end": "suite:end", "test": "test:start", "test end": "test:end", "hook": "hook:start", "hook end": "hook:end", "pass": "test:pass", "fail": "test:fail", "retry": "test:retry", "pending": "test:pending" }; // src/browser/frameworks/mocha.ts var startTime = Date.now(); if (!window.Mocha) { throw new Error("Can't find Mocha attached to the `window` scope, was it installed? Run `npm install mocha` and run again!"); } var BaseReporter = window.Mocha.reporters.html; var HTMLReporter = class extends BaseReporter { constructor(runner, options) { const getElementById = document.getElementById.bind(document); document.getElementById = () => { var _a, _b; return (_b = (_a = document.querySelector("mocha-framework")) == null ? void 0 : _a.shadowRoot) == null ? void 0 : _b.querySelector("#mocha"); }; super(runner, options); document.getElementById = getElementById; } addCodeToggle() { } }; var _root, _spec, _require, _hookResolver, _runnerEvents, _isMinified, _MochaFramework_instances, onFinish_fn, handleSocketMessage_fn, handleHookResult_fn, getHook_fn, hookTrigger_fn, sendTestReport_fn; var MochaFramework = class extends HTMLElement { constructor() { super(); __privateAdd(this, _MochaFramework_instances); __privateAdd(this, _root); __privateAdd(this, _spec); __privateAdd(this, _require); __privateAdd(this, _hookResolver, /* @__PURE__ */ new Map()); __privateAdd(this, _runnerEvents, []); __privateAdd(this, _isMinified, false); __privateSet(this, _root, this.attachShadow({ mode: "open" })); __privateSet(this, _spec, this.getAttribute("spec")); __privateSet(this, _require, window.__wdioEnv__.args.require || []); delete window.__wdioEnv__.args.require; if (!__privateGet(this, _spec)) { throw new Error('"spec" attribute required but not set'); } mocha.setup({ ...window.__wdioEnv__.args, reporter: HTMLReporter }); } static get observedAttributes() { return ["minified"]; } get spec() { return __privateGet(this, _spec); } connectedCallback() { var _a; __privateGet(this, _root).appendChild(template.content.cloneNode(true)); (_a = __privateGet(this, _root).querySelector(".btnCollapseExpand")) == null ? void 0 : _a.addEventListener("click", () => { if (__privateGet(this, _isMinified)) { this.shadowRoot.host.removeAttribute("minified"); } else { this.shadowRoot.host.setAttribute("minified", "minified"); } }); } attributeChangedCallback(name, oldValue, newValue) { if (name === "minified") { __privateSet(this, _isMinified, typeof newValue === "string"); const reporterElem = __privateGet(this, _root).querySelector(".reporter"); if (reporterElem) { reporterElem.className = __privateGet(this, _isMinified) ? "reporter minified" : "reporter"; } document.body.style.width = "calc(100% - ".concat(__privateGet(this, _isMinified) ? "65px" : "500px", ")"); } } async run() { var _a; const globalTeardownScripts = []; const globalSetupScripts = []; for (const r of __privateGet(this, _require)) { const { mochaGlobalSetup, mochaGlobalTeardown } = await import( /* @vite-ignore */ r ) || {}; if (typeof mochaGlobalSetup === "function") { globalSetupScripts.push(mochaGlobalSetup); } if (typeof mochaGlobalTeardown === "function") { globalTeardownScripts.push(mochaGlobalTeardown); } } const cid = getCID(); if (!cid) { throw new Error('"cid" query parameter is missing'); } const beforeHook = __privateMethod(this, _MochaFramework_instances, getHook_fn).call(this, "beforeHook"); const beforeTest = __privateMethod(this, _MochaFramework_instances, getHook_fn).call(this, "beforeTest"); const afterHook = __privateMethod(this, _MochaFramework_instances, getHook_fn).call(this, "afterHook"); const afterTest = __privateMethod(this, _MochaFramework_instances, getHook_fn).call(this, "afterTest"); setupEnv(cid, window.__wdioEnv__.args, beforeTest, beforeHook, afterTest, afterHook); const file = __privateGet(this, _spec); await import( /* @vite-ignore */ file ); for (const setupScript of globalSetupScripts) { await setupScript(); } (_a = import.meta.hot) == null ? void 0 : _a.on(WDIO_EVENT_NAME, __privateMethod(this, _MochaFramework_instances, handleSocketMessage_fn).bind(this)); const self = this; const mochaBeforeHook = globalThis.before || globalThis.suiteSetup; mochaBeforeHook(async function() { var _a2, _b, _c; const { title, tests, pending, delayed } = ((_b = (_a2 = this.test) == null ? void 0 : _a2.parent) == null ? void 0 : _b.suites[0]) || {}; await __privateMethod(_c = self, _MochaFramework_instances, getHook_fn).call(_c, "beforeSuite")({ ...{ title, tests, pending, delayed }, file }); }); const mochaAfterHook = globalThis.after || globalThis.suiteTeardown; mochaAfterHook(async function() { var _a2, _b, _c; const { title, tests, pending, delayed } = ((_b = (_a2 = this.test) == null ? void 0 : _a2.parent) == null ? void 0 : _b.suites[0]) || {}; await __privateMethod(_c = self, _MochaFramework_instances, getHook_fn).call(_c, "afterSuite")({ ...{ title, tests, pending, delayed }, file, duration: Date.now() - startTime }); }); const spinner = __privateGet(this, _root).querySelector(".lds-ring"); if (spinner) { spinner.remove(); } const runner = mocha.run(async (failures) => { await __privateMethod(this, _MochaFramework_instances, onFinish_fn).call(this, failures); for (const teardownScript of globalTeardownScripts) { await teardownScript(); } }); Object.entries(EVENTS).map(([mochaEvent, wdioEvent]) => runner.on(mochaEvent, (payload) => { __privateGet(this, _runnerEvents).push(formatMessage({ type: wdioEvent, payload, err: payload.err })); })); } }; _root = new WeakMap(); _spec = new WeakMap(); _require = new WeakMap(); _hookResolver = new WeakMap(); _runnerEvents = new WeakMap(); _isMinified = new WeakMap(); _MochaFramework_instances = new WeakSet(); onFinish_fn = async function(failures) { await __privateMethod(this, _MochaFramework_instances, getHook_fn).call(this, "after")(failures, window.__wdioEnv__.capabilities, [__privateGet(this, _spec)]); __privateMethod(this, _MochaFramework_instances, sendTestReport_fn).call(this, { failures, events: __privateGet(this, _runnerEvents) }); console.log("[WDIO] Finished test suite in ".concat(Date.now() - startTime, "ms")); }; handleSocketMessage_fn = function(message) { if (message.type === MESSAGE_TYPES.hookResultMessage) { return __privateMethod(this, _MochaFramework_instances, handleHookResult_fn).call(this, message.value); } }; handleHookResult_fn = function(result) { const resolver = __privateGet(this, _hookResolver).get(result.id); if (!resolver) { return console.warn("[WDIO] couldn't find resolve for id \"".concat(result.id, '"')); } __privateGet(this, _hookResolver).delete(result.id); if (result.error) { return resolver.reject(result.error); } return resolver.resolve(); }; getHook_fn = function(name) { return (...args) => new Promise((resolve, reject) => { var _a; const id = __privateGet(this, _hookResolver).size + 1; const cid = getCID(); if (!cid) { return reject(new Error('"cid" query parameter is missing')); } __privateGet(this, _hookResolver).set(id, { resolve, reject }); args = args.map((arg) => { if (typeof arg !== "object") { return arg; } if ("error" in arg && arg.error instanceof Error) { const errorObject = { // Pull all enumerable properties, supporting properties on custom Errors ...arg.error, // Explicitly pull Error's non-enumerable properties message: arg.error.message, name: arg.error.name, stack: arg.error.stack, type: arg.error.type || arg.error.name, matcherResult: arg.error.matcherResult, expected: arg.error.expected, actual: arg.error.actual }; return { ...arg, error: errorObject }; } return { ...filterTestArgument(arg, __privateGet(this, _spec)), ..."type" in arg && "title" in arg ? { parent: arg.parent } : {}, ..."test" in arg && arg.test ? { test: filterTestArgument(arg.test, __privateGet(this, _spec)) } : {}, ..."currentTest" in arg && arg.currentTest ? { currentTest: filterTestArgument(arg.currentTest, __privateGet(this, _spec)) } : {} }; }); (_a = import.meta.hot) == null ? void 0 : _a.send(WDIO_EVENT_NAME, __privateMethod(this, _MochaFramework_instances, hookTrigger_fn).call(this, { name, id, cid, args })); }); }; hookTrigger_fn = function(value) { return { type: MESSAGE_TYPES.hookTriggerMessage, value: JSON.parse(safeStringify(value)) }; }; sendTestReport_fn = function(value) { var _a; (_a = import.meta.hot) == null ? void 0 : _a.send(WDIO_EVENT_NAME, { type: MESSAGE_TYPES.browserTestResult, value: JSON.parse(safeStringify(value)) }); }; var template = document.createElement("template"); template.innerHTML = /*html*/ '\n<style>\n @import "@wdio/browser-runner/third_party/mocha.css";\n\n .reporter {\n transition: width .3s;\n box-shadow: -5px 0px 10px rgb(0 0 0 / 30%);\n position: absolute;\n top: 0;\n right: 0;\n width: 500px;\n height: 100%;\n margin: 0;\n color: var(--mocha-color);\n background-color: var(--mocha-bg-color);\n background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNjRweCIgaGVpZ2h0PSI2NHB4IiB2aWV3Qm94PSIwIDAgNjQgNjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8dGl0bGU+TG9nbyBSZWd1bGFyPC90aXRsZT4KICAgIDxnIGlkPSJMb2dvLVJlZ3VsYXIiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxyZWN0IGlkPSJSZWN0YW5nbGUiIGZpbGw9IiNFQTU5MDYiIHg9IjAiIHk9IjAiIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCIgcng9IjUiPjwvcmVjdD4KICAgICAgICA8cGF0aCBkPSJNOCwxNiBMOCw0OCBMNiw0OCBMNiwxNiBMOCwxNiBaIE00MywxNiBDNTEuODM2NTU2LDE2IDU5LDIzLjE2MzQ0NCA1OSwzMiBDNTksNDAuODM2NTU2IDUxLjgzNjU1Niw0OCA0Myw0OCBDMzQuMTYzNDQ0LDQ4IDI3LDQwLjgzNjU1NiAyNywzMiBDMjcsMjMuMTYzNDQ0IDM0LjE2MzQ0NCwxNiA0MywxNiBaIE0yNywxNiBMMTQuMTA2LDQ3Ljk5OTIwNzggTDExLjk5OSw0Ny45OTkyMDc4IEwyNC44OTQsMTYgTDI3LDE2IFogTTQzLDE4IEMzNS4yNjgwMTM1LDE4IDI5LDI0LjI2ODAxMzUgMjksMzIgQzI5LDM5LjczMTk4NjUgMzUuMjY4MDEzNSw0NiA0Myw0NiBDNTAuNzMxOTg2NSw0NiA1NywzOS43MzE5ODY1IDU3LDMyIEM1NywyNC4yNjgwMTM1IDUwLjczMTk4NjUsMTggNDMsMTggWiIgaWQ9IkNvbWJpbmVkLVNoYXBlIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPg==);\n background-repeat: no-repeat;\n background-size: 30px;\n background-position: 15px 20px;\n }\n .lds-ring {\n display: inline-block;\n position: absolute;\n top: calc(50% - 40px);\n left: calc(50% - 40px);\n width: 80px;\n height: 80px;\n }\n .lds-ring div {\n box-sizing: border-box;\n display: block;\n position: absolute;\n width: 64px;\n height: 64px;\n margin: 8px;\n border: 4px solid #EA5907;\n border-radius: 50%;\n animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: #EA5907 transparent transparent transparent;\n }\n .lds-ring div:nth-child(1) {\n animation-delay: -0.45s;\n }\n .lds-ring div:nth-child(2) {\n animation-delay: -0.3s;\n }\n .lds-ring div:nth-child(3) {\n animation-delay: -0.15s;\n }\n @keyframes lds-ring {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n }\n .reporter.minified {\n width: 65px;\n }\n\n #mocha {\n margin: 0;\n }\n ul#mocha-report {\n transition: opacity .3s;\n opacity: 1;\n padding: 50px 15px 0 0;\n }\n .minified ul#mocha-report {\n opacity: 0;\n }\n .minified .progress {\n display: block;\n float: none;\n }\n .minified #mocha-stats {\n width: 50px;\n padding-top: 60px;\n }\n .minified #mocha-stats li {\n font-size: .9em;\n }\n\n @keyframes fadeOutIn {\n 0% { opacity: 1; }\n 20% { opacity: 0; }\n 100% { opacity: 1; }\n }\n\n .btnCollapseExpand {\n display: block;\n width: 50px;\n position: absolute;\n height: 50px;\n bottom: 0;\n right: 0;\n transition: transform .3s;\n transform: scale(1) translateX(-434px);\n margin: 10px 8px;\n background: transparent;\n border: 0;\n cursor: pointer;\n }\n .minified .btnCollapseExpand {\n transform: scale(-1) translateX(0px);\n animation-name: fadeOutIn;\n animation-duration: .3s;\n }\n</style>\n<div class="reporter">\n <div id="mocha"></div>\n <div class="lds-ring"><div></div><div></div><div></div><div></div></div>\n <button class="btnCollapseExpand">\n <svg width="50" height="40" viewBox="2 0 32 32" xmlns="http://www.w3.org/2000/svg">\n <path fill="#fff" d="M13.11 29.113c7.243 0 13.113-5.871 13.113-13.113S20.353 2.887 13.11 2.887C5.868 2.887-.003 8.758-.003 16S5.868 29.113 13.11 29.113zm0-25.177c6.652 0 12.064 5.412 12.064 12.064S19.762 28.064 13.11 28.064C6.457 28.064 1.046 22.652 1.046 16S6.457 3.936 13.11 3.936z"/>\n <path fill="#fff" d="m13.906 21.637.742.742L21.026 16l-6.378-6.379-.742.742 5.112 5.112H6.291v1.049h12.727z"/>\n </svg>\n </button>\n</div>\n'; customElements.define("mocha-framework", MochaFramework); // src/browser/setup.ts globalThis.alert = showPopupWarning("alert", void 0); globalThis.confirm = showPopupWarning("confirm", false, true); globalThis.prompt = showPopupWarning("prompt", null, "your value"); var browser = await remote({ automationProtocol: automationProtocolPath, capabilities: window.__wdioEnv__.capabilities }); _setGlobal("browser", browser, window.__wdioEnv__.injectGlobals); _setGlobal("driver", browser, window.__wdioEnv__.injectGlobals); _setGlobal("expect", expect, window.__wdioEnv__.injectGlobals); _setGlobal("$", browser.$.bind(browser), window.__wdioEnv__.injectGlobals); _setGlobal("$$", browser.$$.bind(browser), window.__wdioEnv__.injectGlobals); var mochaFramework = document.querySelector("mocha-framework"); if (mochaFramework) { mochaFramework.run().catch((err) => { if (!err.stack) { return; } return window.__wdioErrors__.push({ message: "".concat(err.message, ": ").concat(err.stack), filename: mochaFramework.spec }); }); }