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

132 lines 6.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebdriverIOBrowsingSession = void 0; require("webdriverio"); const core_1 = require("@serenity-js/core"); const index_js_1 = require("@serenity-js/core/lib/model/index.js"); const web_1 = require("@serenity-js/web"); const index_js_2 = require("../models/index.js"); const WebdriverIOErrorHandler_js_1 = require("./WebdriverIOErrorHandler.js"); const WebdriverIOModalDialogHandler_js_1 = require("./WebdriverIOModalDialogHandler.js"); const WebdriverProtocolErrorCode_js_1 = require("./WebdriverProtocolErrorCode.js"); /** * WebdriverIO-specific implementation of [`BrowsingSession`](https://serenity-js.org/api/web/class/BrowsingSession/). * * @group Models */ class WebdriverIOBrowsingSession extends web_1.BrowsingSession { browser; constructor(browser) { super(); this.browser = browser; if (!browser.$ || !browser.$$) { throw new core_1.LogicError(`WebdriverIO browser object is not initialised yet, so can't be assigned to an actor. Are you trying to instantiate an actor outside of a test or a test hook?`); } } async allPages() { // scan all the active window handles and add any newly opened windows if needed const windowHandles = await this.browser.getWindowHandles(); // remove pages that are no longer open const closedPageIds = this.registeredPageIds() .filter(id => !windowHandles.includes(id.value)); this.deregister(...closedPageIds); // add any new pages that might have been opened (e.g. popup windows) const registeredWindowHandles = new Set(this.registeredPageIds().map(id => id.value)); const newlyOpenedWindowHandles = windowHandles.filter(windowHandle => !registeredWindowHandles.has(windowHandle)); for (const newlyOpenedWindowHandle of newlyOpenedWindowHandles) { const modalDialogHandler = new WebdriverIOModalDialogHandler_js_1.WebdriverIOModalDialogHandler(this.browser); const errorHandler = new WebdriverIOErrorHandler_js_1.WebdriverIOErrorHandler(); errorHandler.setHandlerFor(WebdriverProtocolErrorCode_js_1.WebdriverProtocolErrorCode.UnexpectedAlertOpenError, error => modalDialogHandler.dismiss()); this.register(new index_js_2.WebdriverIOPage(this, this.browser, modalDialogHandler, errorHandler, new index_js_1.CorrelationId(newlyOpenedWindowHandle))); } return super.allPages(); } /** * @param page */ async changeCurrentPageTo(page) { const currentPage = await this.currentPage(); // are we already on this page? if (currentPage.id.equals(page.id)) { return void 0; } // does the new page exist, or has it been closed in the meantime by user action, script, or similar? if (!await page.isPresent()) { return void 0; } // the page seems to be legit, switch to it await this.browser.switchToWindow(page.id.value); // and update the cached reference await super.changeCurrentPageTo(page); } async activeWindowHandle() { try { return await this.browser.getWindowHandle(); } catch (error) { // If the window is closed by user action Webdriver will still hold the reference to the closed window. if (['NoSuchWindowError', 'no such window'].includes(error.name)) { const allHandles = await this.browser.getWindowHandles(); if (allHandles.length > 0) { const handle = allHandles.at(-1); await this.browser.switchToWindow(handle); return handle; } } throw error; } } async currentPage() { const actualCurrentPageHandle = await this.activeWindowHandle(); const actualCurrentPageId = index_js_1.CorrelationId.fromJSON(actualCurrentPageHandle); if (this.currentBrowserPage && this.currentBrowserPage.id.equals(actualCurrentPageId)) { return this.currentBrowserPage; } // Looks like the actual current page is not what we thought the current page was. // Is it one of the pages we are aware of? const allPages = await this.allPages(); const found = allPages.find(page => page.id.equals(actualCurrentPageId)); if (found) { this.currentBrowserPage = found; return this.currentBrowserPage; } // OK, so that's a handle that we haven't seen before, let's register it and set as current page. this.currentBrowserPage = await this.registerCurrentPage(); return this.currentBrowserPage; } async registerCurrentPage() { const pageId = await this.assignPageId(); const modalDialogHandler = new WebdriverIOModalDialogHandler_js_1.WebdriverIOModalDialogHandler(this.browser); const errorHandler = new WebdriverIOErrorHandler_js_1.WebdriverIOErrorHandler(); errorHandler.setHandlerFor(WebdriverProtocolErrorCode_js_1.WebdriverProtocolErrorCode.UnexpectedAlertOpenError, error => modalDialogHandler.dismiss()); const page = new index_js_2.WebdriverIOPage(this, this.browser, modalDialogHandler, errorHandler, pageId); this.register(page); return page; } async assignPageId() { if (this.browser.isMobile) { const context = await this.browser.getContext(); if (typeof context === 'string') { return new index_js_1.CorrelationId(context); } if (context.id) { return new index_js_1.CorrelationId(context.id); } } if (this.browser['getWindowHandle']) { const handle = await this.browser.getWindowHandle(); return new index_js_1.CorrelationId(handle); } return index_js_1.CorrelationId.create(); } browserCapabilities() { return Promise.resolve(this.browser.capabilities); } async discard() { for (const page of await this.allPages()) { await page.discard(); } } } exports.WebdriverIOBrowsingSession = WebdriverIOBrowsingSession; //# sourceMappingURL=WebdriverIOBrowsingSession.js.map