UNPKG

@serenity-js/webdriverio

Version:

Adapter that integrates @serenity-js/web with the latest stable version of WebdriverIO, enabling Serenity/JS reporting and using the Screenplay Pattern to write web and mobile test scenarios

258 lines 10.4 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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.WebdriverIOPage = void 0; require("webdriverio"); const node_url_1 = require("node:url"); const core_1 = require("@serenity-js/core"); const web_1 = require("@serenity-js/web"); const scripts = __importStar(require("@serenity-js/web/lib/scripts/index.js")); const index_js_1 = require("./locators/index.js"); const WebdriverIOCookie_js_1 = require("./WebdriverIOCookie.js"); const WebdriverIOPageElement_js_1 = require("./WebdriverIOPageElement.js"); /** * WebdriverIO-specific implementation of [`Page`](https://serenity-js.org/api/web/class/Page/). * * @group Models */ class WebdriverIOPage extends web_1.Page { browser; errorHandler; lastScriptExecutionSummary; /* eslint-disable unicorn/consistent-function-scoping */ dehydrator = new web_1.ArgumentDehydrator((item) => item instanceof web_1.PageElement, (item) => item.nativeElement()); /* eslint-enable */ constructor(session, browser, modalDialogHandler, errorHandler, pageId) { super(session, new index_js_1.WebdriverIORootLocator(browser), modalDialogHandler, pageId); this.browser = browser; this.errorHandler = errorHandler; } createPageElement(nativeElement) { return new WebdriverIOPageElement_js_1.WebdriverIOPageElement(new index_js_1.WebdriverIOExistingElementLocator(this.rootLocator, new web_1.ByCss(String(nativeElement.selector)), this.errorHandler, nativeElement)); } locate(selector) { return new WebdriverIOPageElement_js_1.WebdriverIOPageElement(new index_js_1.WebdriverIOLocator(this.rootLocator, selector, this.errorHandler)); } locateAll(selector) { return core_1.List.of(new web_1.PageElementsLocator(new index_js_1.WebdriverIOLocator(this.rootLocator, selector, this.errorHandler))); } async navigateTo(destination) { await this.inContextOfThisPage(() => this.browser.url(destination)); await this.resetState(); } async navigateBack() { await this.inContextOfThisPage(() => this.browser.back()); await this.resetState(); } async navigateForward() { await this.inContextOfThisPage(() => this.browser.forward()); await this.resetState(); } async reload() { await this.inContextOfThisPage(() => this.browser.refresh()); await this.resetState(); } async sendKeys(keys) { const keySequence = keys.map(key => { if (!web_1.Key.isKey(key)) { return key; } return key.utf16codePoint; }); await this.inContextOfThisPage(() => this.browser.keys(keySequence)); } async executeScript(script, ...args) { const serialisedScript = typeof script === 'function' ? String(script) : String(`function script() { ${script} }`); const executableScript = new Function(` var parameters = (${scripts.rehydrate}).apply(null, arguments); return (${serialisedScript}).apply(null, parameters); `); const result = await this.inContextOfThisPage(async () => { const dehydratedArguments = await this.dehydrator.dehydrate(args); return await this.browser.execute(executableScript, ...dehydratedArguments); }); this.lastScriptExecutionSummary = new LastScriptExecutionSummary(result); return result; } async executeAsyncScript(script, ...args) { const serialisedScript = typeof script === 'function' ? String(script) : String(`function script() { ${script} }`); const executableScript = new Function(` var args = Array.prototype.slice.call(arguments, 0, -1); var callback = arguments[arguments.length - 1]; var parameters = (${scripts.rehydrate}).apply(null, args); (${serialisedScript}).apply(null, parameters.concat(callback)); `); const result = await this.inContextOfThisPage(async () => { const dehydratedArguments = await this.dehydrator.dehydrate(args); return this.browser.executeAsync(executableScript, ...dehydratedArguments); }); this.lastScriptExecutionSummary = new LastScriptExecutionSummary(result); return result; } lastScriptExecutionResult() { if (!this.lastScriptExecutionSummary) { throw new core_1.LogicError(`Make sure to execute a script before checking on the result`); } // Selenium returns `null` when the script it executed returns `undefined` // so we're mapping the result back. return this.lastScriptExecutionSummary.result === null ? undefined : this.lastScriptExecutionSummary.result; } async takeScreenshot() { return await this.inContextOfThisPage(async () => { try { return await this.browser.takeScreenshot(); } catch (error) { if (error.name === 'ProtocolError' && error.message.includes('Target closed')) { throw new web_1.BrowserWindowClosedError(`Couldn't take screenshot since the browser window is already closed`, error); } throw error; } }); } async cookie(name) { return new WebdriverIOCookie_js_1.WebdriverIOCookie(this.browser, name); } async setCookie(cookieData) { return await this.inContextOfThisPage(() => { return this.browser.setCookies({ name: cookieData.name, value: cookieData.value, path: cookieData.path, domain: cookieData.domain, secure: cookieData.secure, httpOnly: cookieData.httpOnly, expiry: cookieData.expiry ? cookieData.expiry.toSeconds() : undefined, // see https://w3c.github.io/webdriver-bidi/#type-network-Cookie sameSite: cookieData?.sameSite?.toLowerCase(), }); }); } async deleteAllCookies() { return await this.inContextOfThisPage(() => { return this.browser.deleteCookies(); }); } async title() { return await this.inContextOfThisPage(() => this.browser.execute(() => document.title)); } async name() { return await this.inContextOfThisPage(() => { return this.browser.execute(() => window.name); }); } async url() { return await this.inContextOfThisPage(async () => { return new node_url_1.URL(await this.browser.execute(() => window.location.href)); }); } async viewportSize() { return await this.inContextOfThisPage(async () => { const calculatedViewportSize = await this.browser.execute(` return { width: Math.max(document.documentElement.clientWidth, window.innerWidth || 0), height: Math.max(document.documentElement.clientHeight, window.innerHeight || 0), } `); // Chrome headless hard-codes window.innerWidth and window.innerHeight to 0 if (calculatedViewportSize.width > 0 && calculatedViewportSize.height > 0) { return calculatedViewportSize; } return this.browser.getWindowSize(); }); } async setViewportSize(size) { return await this.inContextOfThisPage(async () => { await this.browser.setViewport(size); }); } async close() { await this.resetState(); await this.inContextOfThisPage(() => this.browser.closeWindow()); } async closeOthers() { await this.session.closePagesOtherThan(this); } async isPresent() { const allPages = await this.session.allPages(); for (const page of allPages) { if (page === this) { return true; } } return false; } async resetState() { this.lastScriptExecutionSummary = undefined; await this.rootLocator.switchToMainFrame(); await this.modalDialogHandler.reset(); } async discard() { await this.modalDialogHandler.discard(); } async inContextOfThisPage(action) { let originalCurrentPage; try { originalCurrentPage = await this.session.currentPage(); await this.session.changeCurrentPageTo(this); return await action(); } catch (error) { return await this.errorHandler.executeIfHandled(error, action); } finally { await this.session.changeCurrentPageTo(originalCurrentPage); } } } exports.WebdriverIOPage = WebdriverIOPage; /** * @package */ class LastScriptExecutionSummary { result; constructor(result) { this.result = result; } } //# sourceMappingURL=WebdriverIOPage.js.map