UNPKG

@serenity-js/playwright

Version:

Adapter that integrates @serenity-js/web with Playwright, enabling Serenity/JS reporting and using the Screenplay Pattern to write component and end-to-end test scenarios

229 lines (228 loc) 8.85 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.PlaywrightPage = void 0; 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")); const promised_1 = require("../promised"); const locators_1 = require("./locators"); const PlaywrightModalDialogHandler_1 = require("./PlaywrightModalDialogHandler"); const PlaywrightPageElement_1 = require("./PlaywrightPageElement"); /** * Playwright-specific implementation of [`Page`](https://serenity-js.org/api/web/class/Page/). * * @group Models */ class PlaywrightPage extends web_1.Page { page; options; lastScriptExecutionSummary; /* eslint-disable unicorn/consistent-function-scoping */ dehydrator = new web_1.ArgumentDehydrator((item) => item instanceof web_1.PageElement, async (item) => { const nativeElement = await item.nativeElement(); return nativeElement.elementHandle(); }); /* eslint-enable */ static current() { return super.current(); } constructor(session, page, options, pageId) { super(session, new locators_1.PlaywrightRootLocator(page), new PlaywrightModalDialogHandler_1.PlaywrightModalDialogHandler(page), pageId); this.page = page; this.options = options; } createPageElement(nativeElement) { return new PlaywrightPageElement_1.PlaywrightPageElement(new locators_1.PlaywrightExistingElementLocator(this.rootLocator, new web_1.ByDeepCss(nativeElement._selector), nativeElement)); } locate(selector) { return new PlaywrightPageElement_1.PlaywrightPageElement(new locators_1.PlaywrightLocator(this.rootLocator, selector)); } locateAll(selector) { return core_1.List.of(new web_1.PageElementsLocator(new locators_1.PlaywrightLocator(this.rootLocator, selector))); } async navigateTo(destination) { await this.page.goto(destination, { waitUntil: this.options?.defaultNavigationWaitUntil }); await this.resetState(); } async navigateBack() { await this.page.goBack({ waitUntil: this.options?.defaultNavigationWaitUntil }); await this.resetState(); } async navigateForward() { await this.page.goForward({ waitUntil: this.options?.defaultNavigationWaitUntil }); await this.resetState(); } async reload() { await this.page.reload({ waitUntil: this.options?.defaultNavigationWaitUntil }); await this.resetState(); } async sendKeys(keys) { const keySequence = keys.map(key => { if (!web_1.Key.isKey(key)) { return key; } return key.devtoolsName; }); await this.page.keyboard.press(keySequence.join('+')); } async executeScript(script, ...args) { const serialisedScript = typeof script === 'function' ? String(script) : String(`function script() { ${script} }`); const executableScript = new Function(` const parameters = (${scripts.rehydrate}).apply(null, arguments[0]); return (${serialisedScript}).apply(null, parameters); `); const dehydratedArguments = await this.dehydrator.dehydrate(args); const result = await this.rootLocator.evaluate(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(` const parameters = (${scripts.rehydrate}).apply(null, arguments[0]); return new Promise((resolve, reject) => { try { return (${serialisedScript}).apply(null, parameters.concat(resolve)); } catch (error) { return reject(error); } }) `); const dehydratedArguments = await this.dehydrator.dehydrate(args); const result = await this.rootLocator.evaluate(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`); } return this.lastScriptExecutionSummary.result; } async takeScreenshot() { try { const screenshot = await this.page.screenshot(); return screenshot.toString('base64'); } catch (error) { if (error?.message.includes('Target page, context or browser has been closed')) { throw new web_1.BrowserWindowClosedError(`Couldn't take screenshot since the browser window is already closed`, error); } throw error; } } async cookie(name) { return this.session.cookie(name); } async setCookie(cookieData) { const url = await this.page.url(); const cookie = { name: cookieData.name, value: cookieData.value, domain: cookieData.domain, path: cookieData.path, url: !(cookieData.domain && cookieData.path) // eslint-disable-line unicorn/no-negated-condition ? url : undefined, secure: cookieData.secure, httpOnly: cookieData.httpOnly, expires: cookieData.expiry ? cookieData.expiry.toSeconds() : undefined, sameSite: cookieData.sameSite, }; return this.session.setCookie(cookie); } async deleteAllCookies() { await this.session.deleteAllCookies(); } async title() { const currentFrame = await this.currentFrame(); return currentFrame.title(); } async name() { const currentFrame = await this.currentFrame(); return currentFrame.evaluate(() => window.name); } async url() { const currentFrame = await this.currentFrame(); return new node_url_1.URL(currentFrame.url()); } async viewportSize() { return this.page.viewportSize(); } async setViewportSize(size) { await this.page.setViewportSize(size); } async close() { await this.resetState(); await this.modalDialogHandler.discard(); await this.page.close(); } async closeOthers() { await this.session.closePagesOtherThan(this); } isPresent() { return (0, promised_1.promised)(!this.page.isClosed()); } async nativePage() { return (0, promised_1.promised)(this.page); } async resetState() { this.lastScriptExecutionSummary = undefined; await this.rootLocator.switchToMainFrame(); await this.modalDialogHandler.reset(); } async currentFrame() { return await this.rootLocator.nativeElement(); } } exports.PlaywrightPage = PlaywrightPage; /** * @package */ class LastScriptExecutionSummary { result; constructor(result) { this.result = result; } } //# sourceMappingURL=PlaywrightPage.js.map