UNPKG

qunit-harness

Version:

A library for running qunit tests on a local machine and in the SauceLabs environment.

380 lines (289 loc) 13.6 kB
'use strict'; var _createClass = require('babel-runtime/helpers/create-class').default; var _classCallCheck = require('babel-runtime/helpers/class-call-check').default; var _regeneratorRuntime = require('babel-runtime/regenerator').default; var _Object$keys = require('babel-runtime/core-js/object/keys').default; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default').default; exports.__esModule = true; var _webdriver = require('webdriver'); var _webdriver2 = _interopRequireDefault(_webdriver); var _wdioProtocols = require('@wdio/protocols'); var _lodash = require('lodash'); var _request = require('./request'); var _request2 = _interopRequireDefault(_request); var _utilsWait = require('../utils/wait'); var _utilsWait2 = _interopRequireDefault(_utilsWait); var _utilsIsSafari15 = require('../utils/is-safari-15'); var _utilsIsSafari152 = _interopRequireDefault(_utilsIsSafari15); var CHECK_TEST_RESULT_DELAY = 10 * 1000; var MAX_JOB_RESTART_COUNT = 3; var BROWSER_INIT_RETRIES = 3; var BROWSER_INIT_TIMEOUT = 9 * 60 * 1000; var SAUCE_API_HOST = 'saucelabs.com'; var SAUCE_API_PORT = 80; // NOTE: Saucelabs cannot start tests in Safari 15 immediately. // So, we are forced to add delay before test execution. var TEST_RUN_DELAY_FOR_SAFARI_15 = 30 * 1000; //Job var Job = (function () { function Job(options, browserInfo) { _classCallCheck(this, Job); this.options = { username: options.username, accessKey: options.accessKey, build: options.build, testName: options.testName, tags: options.tags, urls: options.urls, tunnelIdentifier: options.tunnelIdentifier, testsTimeout: options.timeout * 1000 }; this.requestAdapter = new _request2.default(this.options.username, this.options.accessKey); this.browserInfo = browserInfo; this.browser = null; this.status = Job.STATUSES.INITIALIZED; this.restartCount = 0; this.startTestsTime = null; var platformName = browserInfo.platform || browserInfo.platformName || ''; var browserName = browserInfo.browserName || ''; var plaformVersion = browserInfo.version || browserInfo.platformVersion || ''; this.platform = [platformName, browserName, plaformVersion]; } Job.prototype._getTestResult = function _getTestResult() { var testResult, windowErrorMessage, ie11ErrorMessage; return _regeneratorRuntime.async(function _getTestResult$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: testResult = null; case 1: if (testResult) { context$2$0.next = 20; break; } if (!(new Date() - this.startTestsTime > this.options.testsTimeout)) { context$2$0.next = 4; break; } throw new Error('Test exceeded maximum duration'); case 4: context$2$0.next = 6; return _regeneratorRuntime.awrap(_utilsWait2.default(CHECK_TEST_RESULT_DELAY)); case 6: context$2$0.prev = 6; context$2$0.next = 9; return _regeneratorRuntime.awrap(this.browser.executeScript('return window.global_test_results', [])); case 9: testResult = context$2$0.sent; context$2$0.next = 18; break; case 12: context$2$0.prev = 12; context$2$0.t0 = context$2$0['catch'](6); windowErrorMessage = 'window has no properties'; ie11ErrorMessage = ['Error response status: 13, , ', 'UnknownError - An unknown server-side error occurred while processing the command. ', 'Selenium error: JavaScript error (WARNING: The server did not provide any stacktrace information)'].join(''); if (!(context$2$0.t0.message.indexOf(windowErrorMessage) < 0 && context$2$0.t0.message.indexOf(ie11ErrorMessage) < 0)) { context$2$0.next = 18; break; } throw context$2$0.t0; case 18: context$2$0.next = 1; break; case 20: return context$2$0.abrupt('return', testResult); case 21: case 'end': return context$2$0.stop(); } }, null, this, [[6, 12]]); }; Job.prototype._getJobResult = function _getJobResult() { var testResult; return _regeneratorRuntime.async(function _getJobResult$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.status = Job.STATUSES.IN_PROGRESS; this.startTestsTime = new Date(); context$2$0.next = 4; return _regeneratorRuntime.awrap(this._getTestResult()); case 4: testResult = context$2$0.sent; this.status = Job.STATUSES.COMPLETED; context$2$0.prev = 6; context$2$0.next = 9; return _regeneratorRuntime.awrap(this._publishTestResult(testResult)); case 9: context$2$0.next = 14; break; case 11: context$2$0.prev = 11; context$2$0.t0 = context$2$0['catch'](6); this._reportError('An error occurred while the test result was being published: ' + context$2$0.t0); case 14: return context$2$0.abrupt('return', { url: 'https://' + SAUCE_API_HOST + '/jobs/' + this.browser.sessionId, platform: this.platform, result: testResult, job_id: this.browser.sessionId }); case 15: case 'end': return context$2$0.stop(); } }, null, this, [[6, 11]]); }; Job.prototype._reportError = function _reportError(error) { console.log('The task (' + this.platform + ') failed: ' + error); }; Job.prototype._publishTestResult = function _publishTestResult(testResult) { var testSuccess, data; return _regeneratorRuntime.async(function _publishTestResult$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: testSuccess = (testResult.errors.length === 0 || _Object$keys(testResult.errors).length === 0) && testResult.failed === 0; data = { public: 'public', passed: testSuccess, 'custom-data': { 'qunit': testResult } }; context$2$0.next = 4; return _regeneratorRuntime.awrap(this.requestAdapter.put('/v1/' + this.options.username + '/jobs/' + this.browser.sessionId, data)); case 4: case 'end': return context$2$0.stop(); } }, null, this); }; Job.prototype.run = function run() { var jobResult, jobFailed, initBrowserParams, executeCommand; return _regeneratorRuntime.async(function run$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: jobResult = null; jobFailed = false; initBrowserParams = { name: this.options.testName, tags: this.options.tags, build: this.options.build, tunnelIdentifier: this.options.tunnelIdentifier }; _lodash.assign(initBrowserParams, this.browserInfo); this.status = Job.STATUSES.INIT_BROWSER; executeCommand = _wdioProtocols.WebDriverProtocol['/session/:sessionId/execute/sync']; _wdioProtocols.WebDriverProtocol['/session/:sessionId/execute'] = executeCommand; context$2$0.prev = 7; context$2$0.next = 10; return _regeneratorRuntime.awrap(_webdriver2.default.newSession({ protocol: 'http', hostname: 'ondemand.' + SAUCE_API_HOST, port: SAUCE_API_PORT, user: this.options.username, key: this.options.accessKey, capabilities: initBrowserParams, logLevel: 'error', connectionRetryTimeout: BROWSER_INIT_TIMEOUT, connectionRetryCount: BROWSER_INIT_RETRIES, path: '/wd/hub', automationProtocol: 'webdriver' })); case 10: this.browser = context$2$0.sent; if (!_utilsIsSafari152.default(initBrowserParams)) { context$2$0.next = 14; break; } context$2$0.next = 14; return _regeneratorRuntime.awrap(_utilsWait2.default(TEST_RUN_DELAY_FOR_SAFARI_15)); case 14: context$2$0.next = 16; return _regeneratorRuntime.awrap(this.browser.navigateTo(this.options.urls[0])); case 16: context$2$0.next = 22; break; case 18: context$2$0.prev = 18; context$2$0.t0 = context$2$0['catch'](7); this._reportError('An error occurred while the browser was being initialized: ' + context$2$0.t0); jobFailed = true; case 22: if (jobFailed) { context$2$0.next = 41; break; } context$2$0.prev = 23; context$2$0.next = 26; return _regeneratorRuntime.awrap(this._getJobResult()); case 26: jobResult = context$2$0.sent; context$2$0.next = 33; break; case 29: context$2$0.prev = 29; context$2$0.t1 = context$2$0['catch'](23); this._reportError(context$2$0.t1); jobFailed = true; case 33: context$2$0.prev = 33; context$2$0.next = 36; return _regeneratorRuntime.awrap(this.browser.deleteSession()); case 36: context$2$0.next = 41; break; case 38: context$2$0.prev = 38; context$2$0.t2 = context$2$0['catch'](33); this._reportError('An error occured while the browser was being closed: ' + context$2$0.t2); case 41: if (!jobFailed) { context$2$0.next = 52; break; } if (!(++this.restartCount < MAX_JOB_RESTART_COUNT)) { context$2$0.next = 49; break; } console.log('Attempt ' + this.restartCount + ' to restart the task (' + this.platform + ')'); context$2$0.next = 46; return _regeneratorRuntime.awrap(this.run()); case 46: jobResult = context$2$0.sent; context$2$0.next = 52; break; case 49: jobResult = { platform: this.platform, job_id: this.browser.sessionId }; if (this.status === Job.STATUSES.IN_PROGRESS) jobResult.url = 'https://' + SAUCE_API_HOST + '/jobs/' + this.browser.sessionId; this.status = Job.STATUSES.FAILED; case 52: return context$2$0.abrupt('return', jobResult); case 53: case 'end': return context$2$0.stop(); } }, null, this, [[7, 18], [23, 29], [33, 38]]); }; Job.prototype.getStatus = function getStatus() { return this.status; }; _createClass(Job, null, [{ key: 'STATUSES', value: { INIT_BROWSER: 'init browser', INITIALIZED: 'initialized', IN_PROGRESS: 'in progress', COMPLETED: 'completed', FAILED: 'failed' }, enumerable: true }]); return Job; })(); exports.default = Job; module.exports = exports.default; // NOTE: this error may occur while testing against internet explorer 11. // This may happen because the IE driver sometimes throws an unknown error // when executing an expression with the 'window' object.