From da1207c3a7282e6098fa9e63eb50a9af5afb47ab Mon Sep 17 00:00:00 2001 From: step2yeung Date: Wed, 1 May 2019 11:52:40 -0700 Subject: [PATCH] Allow graceful exit when async iterator failes to get a module. Add emberExamExitOnError flag to hard fail --- addon-test-support/-private/async-iterator.js | 30 +++++++++++++------ .../-private/ember-exam-qunit-test-loader.js | 5 ++-- node-tests/acceptance/exam-test.js | 4 +-- tests/unit/qunit/async-iterator-test.js | 22 +++++++++++--- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/addon-test-support/-private/async-iterator.js b/addon-test-support/-private/async-iterator.js index ed478df0..3cc5e1af 100644 --- a/addon-test-support/-private/async-iterator.js +++ b/addon-test-support/-private/async-iterator.js @@ -1,5 +1,7 @@ 'use strict'; +const iteratorCompleteResponse = { done: true, value: null }; + /** * A class to iterate a sequencial set of asynchronous events. * @@ -17,6 +19,7 @@ export default class AsyncIterator { // Set a timeout value from either url parameter or default timeout value, 15 s. this._timeout = options.timeout || 15; this._browserId = options.browserId; + this._emberExamExitOnError = options.emberExamExitOnError; testem.on(this._response, this._boundHandleResponse); } @@ -88,20 +91,29 @@ export default class AsyncIterator { /** * Set a timeout to reject a promise if it doesn't get response within the timeout threshold. * - * @param {*} reject + * @param {*} resolve */ - _setTimeout(reject) { + _setTimeout(resolve, reject) { clearTimeout(this.timeout); this.timer = setTimeout(() => { if (!this._waiting) { return; } - let err = new Error( - `EmberExam: Promise timed out after ${ + + if (this._emberExamExitOnError) { + let err = new Error( + `EmberExam: Promise timed out after ${ + this._timeout + } s while waiting for response for ${this._request}` + ); + reject(err); + } else { + // eslint-disable-next-line no-console + console.error(`EmberExam: Promise timed out after ${ this._timeout - } s while waiting for response for ${this._request}` - ); - reject(err); + } s while waiting for response for ${this._request}. Closing browser to exit gracefully.`); + resolve(iteratorCompleteResponse); + } }, this._timeout * 1000); } @@ -113,7 +125,7 @@ export default class AsyncIterator { */ next() { if (this._done) { - return Promise.resolve({ done: true, value: null }); + return Promise.resolve(iteratorCompleteResponse); } if (this._current) { return this._current.promise; @@ -123,7 +135,7 @@ export default class AsyncIterator { let promise = new Promise((_resolve, _reject) => { resolve = _resolve; reject = _reject; - this._setTimeout(reject); + this._setTimeout(resolve, reject); }); this._current = { diff --git a/addon-test-support/-private/ember-exam-qunit-test-loader.js b/addon-test-support/-private/ember-exam-qunit-test-loader.js index 1772df40..4fb937db 100644 --- a/addon-test-support/-private/ember-exam-qunit-test-loader.js +++ b/addon-test-support/-private/ember-exam-qunit-test-loader.js @@ -116,8 +116,9 @@ export default class EmberExamQUnitTestLoader extends TestLoader { const nextModuleAsyncIterator = new AsyncIterator(this._testem, { request: 'testem:next-module-request', response: 'testem:next-module-response', - timeout: getUrlParams().get('asyncTimeout'), - browserId: getUrlParams().get('browser') + timeout: this._urlParams.get('asyncTimeout'), + browserId: this._urlParams.get('browser'), + emberExamExitOnError: this._urlParams.get('_emberExamExitOnError'), }); const nextModuleHandler = () => { diff --git a/node-tests/acceptance/exam-test.js b/node-tests/acceptance/exam-test.js index 3fcf4426..89db1507 100644 --- a/node-tests/acceptance/exam-test.js +++ b/node-tests/acceptance/exam-test.js @@ -16,7 +16,7 @@ function getNumberOfTests(str) { return match && parseInt(match[1], 10); } -const TOTAL_NUM_TESTS = 47; // Total Number of tests without the global 'Ember.onerror validation tests' +const TOTAL_NUM_TESTS = 48; // Total Number of tests without the global 'Ember.onerror validation tests' function getTotalNumberOfTests(output) { // In ember-qunit 3.4.0, this new check was added: https://github.com/emberjs/ember-qunit/commit/a7e93c4b4b535dae62fed992b46c00b62bfc83f4 @@ -538,7 +538,7 @@ describe('Acceptance | Exam Command', function() { assertOutput(output, 'Browser Id', ["2"]); assert.equal( getNumberOfTests(output), - 23, + 24, 'ran all of the tests for browser two' ); }); diff --git a/tests/unit/qunit/async-iterator-test.js b/tests/unit/qunit/async-iterator-test.js index 899e3392..83bdce19 100644 --- a/tests/unit/qunit/async-iterator-test.js +++ b/tests/unit/qunit/async-iterator-test.js @@ -146,21 +146,35 @@ test('should dispose after iteration.', function(assert) { }); }); -test('should throw a timout error if request is not handled within 2s', function(assert) { +test('should resolve with iterator finishing if request is not handled within 2s', function(assert) { assert.expect(1); - const done = assert.async(); const iteratorOfPromises = new AsyncIterator(this.testem, { request: 'next-module-request', response: 'next-module-response', timeout: 2 }); - iteratorOfPromises.next().catch(err => { + return iteratorOfPromises.next().then(res => { + assert.deepEqual(res.done, true); + }); +}); + +test('should resolve a timeout error if request is not handled within 2s when emberExamExitOnError is true', function(assert) { + assert.expect(1); + const iteratorOfPromises = new AsyncIterator(this.testem, { + request: 'next-module-request', + response: 'next-module-response', + timeout: 2, + emberExamExitOnError: true, + }); + + return iteratorOfPromises.next().then(() => { + assert.ok(false, 'Promise should not resolve, expecting reject'); + },err => { assert.deepEqual( err.message, 'EmberExam: Promise timed out after 2 s while waiting for response for next-module-request' ); - done(); }); });