UNPKG

qape

Version:

Monkey testing library

175 lines (138 loc) 4.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _puppeteer = _interopRequireDefault(require("puppeteer")); var _events = _interopRequireDefault(require("events")); var _messanger = require("../messanger"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * These errors will not cause test run to exit as failrue */ const KNOWN_FATAL_ERROR_MESSAGES = ['Page crashed!' // See https://github.com/seznam/QApe/issues/13 ]; /** * Browser instance */ class Browser { /** * @param {Object} config */ constructor(config) { this._config = config; this._browser = null; this._page = null; this._pageErrorHandler = null; this._unknownExecutionErrorOccured = false; } /** * @returns {puppeteer.Browser} */ get browser() { return this._browser; } /** * @returns {puppeteer.Page} */ get page() { return this._page; } /** * Page error handler recieves 'page-error' event * whenever an error occures on the page. * Action should add listener to this handler and * listen to the 'page-error' event to see if the action * caused an error on the page. * @returns {Function} */ get pageErrorHandler() { return this._pageErrorHandler; } /** * Test run with execution error will fail only when unknown execution error occured */ get unknownExecutionErrorOccured() { return this._unknownExecutionErrorOccured; } /** * Initializes browser instance * @returns {Promise<Browser>} */ async initBrowser() { this._browser = await this._getBrowser(); this._page = (await this._browser.pages())[0]; this._initFatalErrorHandler(); await this._initPageErrorHandler(); await this._page.setDefaultNavigationTimeout(this._config.defaultNavigationTimeout); return this; } /** * Clears browser instance * @returns {Promise} Resolves when the instance is cleared */ async clear() { delete this._pageErrorHandler; await this._browser.close(); } /** * Gets browser instance from puppeteer. * If there is a config.browserWebSocketEndpoint set, * it will connect to remote chrome instance, * otherwise it will create new instance locally * @returns {Promise<puppeteer.Browser>} */ _getBrowser() { if (this._config.browserWebSocketEndpoint) { return _puppeteer.default.connect(Object.assign(this._config.defaultBrowserSettings, { browserWSEndpoint: this._config.browserWebSocketEndpoint })); } return _puppeteer.default.launch(Object.assign(this._config.defaultBrowserSettings, { headless: !this._config.headlessModeDisabled })); } /** * Whenever a page error occures, there is a strong possibility, * that QApe tester is in inconsistent state. * So it will try to clear the instance and wait for the new * test run. */ _initFatalErrorHandler() { this._page.on('error', error => { let msg = error.stack + '\n' + 'Because of the error above the browser instance ' + 'has been cleared and may cause an additional error ' + 'in current test run. You can ignore it, since QApe ' + 'tester should recover by itself.'; (0, _messanger.report)('browser:error', { error: msg }); this._handleUnknownExecutionErrors(error); this.clear(); }); } /** * Sets unknown execution error indicator * @param {Object} error */ _handleUnknownExecutionErrors(error) { if (KNOWN_FATAL_ERROR_MESSAGES.some(message => error.message.includes(message))) { return; } this._unknownExecutionErrorOccured = true; } /** * Initializes pageErrorHandler, exposes it to the * page instance and loads config.pageErrorHandler * @returns {Promise} Resolves when handler is initialized */ async _initPageErrorHandler() { this._pageErrorHandler = this._getEventEmitter(); await this._page.exposeFunction('qapeError', error => this._pageErrorHandler.emit('page-error', error)); await this._page.evaluateOnNewDocument(this._config.pageErrorHandler); } /** * @returns {EventEmitter} */ _getEventEmitter() { return new _events.default(); } } exports.default = Browser;