Skip to content

Commit d6024be

Browse files
committed
Initial implementation of #244 - require explicit test.async
1 parent ff736c4 commit d6024be

18 files changed

+216
-151
lines changed

lib/runner.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ function Runner(opts) {
3333
type: 'test',
3434
serial: false,
3535
exclusive: false,
36-
skipped: false
36+
skipped: false,
37+
async: false
3738
}, this._addFn.bind(this));
3839
}
3940

@@ -47,7 +48,8 @@ var chainableFunctions = {
4748
skip: {skipped: true},
4849
only: {exclusive: true},
4950
beforeEach: {type: 'beforeEach'},
50-
afterEach: {type: 'afterEach'}
51+
afterEach: {type: 'afterEach'},
52+
async: {async: true}
5153
};
5254

5355
function makeChain(defaults, parentAdd) {

lib/test.js

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ function Test(title, fn) {
2828
this.duration = null;
2929
this.context = {};
3030

31+
// TODO(jamestalmage): make this an optional constructor arg instead of having Runner set it after the fact.
32+
// metadata should just always exist, otherwise it requires a bunch of ugly checks all over the place.
33+
// I will fix this correctly in the upstream PR.
34+
this.metadata = {};
35+
3136
// store the time point before test execution
3237
// to calculate the total time spent in test
3338
this._timeStart = null;
@@ -47,7 +52,9 @@ module.exports = Test;
4752
Test.prototype._assert = function () {
4853
this.assertCount++;
4954

50-
if (this.assertCount === this.planCount) {
55+
// TODO(jamestalmage): no only auto-ends in "declared" async mode `test.async(...)`. Should we drop auto-end behavior all together?
56+
// https://github.com/sindresorhus/ava/issues/244#issuecomment-158705839
57+
if (this.metadata.async && this.assertCount === this.planCount) {
5158
setImmediate(this.exit.bind(this));
5259
}
5360
};
@@ -123,27 +130,38 @@ Test.prototype.run = function () {
123130
ret = observableToPromise(ret);
124131

125132
if (isPromise(ret)) {
126-
ret
127-
.then(function () {
128-
if (!self.planCount || self.planCount === self.assertCount) {
129-
self.exit();
130-
}
131-
})
132-
.catch(function (err) {
133-
self.assertError = new assert.AssertionError({
134-
actual: err,
135-
message: 'Promise rejected → ' + err,
136-
operator: 'promise'
137-
});
138-
133+
if (!this.metadata.async) {
134+
ret = ret.then(function () {
139135
self.exit();
140136
});
137+
}
138+
139+
ret.catch(function (err) {
140+
self.assertError = new assert.AssertionError({
141+
actual: err,
142+
message: 'Promise rejected → ' + err,
143+
operator: 'promise'
144+
});
145+
146+
self.exit();
147+
});
148+
} else if (!this.metadata.async) {
149+
this.exit();
141150
}
142151

143152
return this.promise.promise;
144153
};
145154

146-
Test.prototype.end = function (err) {
155+
Object.defineProperty(Test.prototype, 'end', {
156+
get: function () {
157+
if (this.metadata.async) {
158+
return this._end;
159+
}
160+
throw new Error('t.end is not supported in this context. To use t.end as a callback, you must explicitly declare the test asynchronous via `test.async(testName, fn)` ');
161+
}
162+
});
163+
164+
Test.prototype._end = function (err) {
147165
if (err) {
148166
this.assertError = new assert.AssertionError({
149167
actual: err,

test/fixture/circular-reference-on-assertion.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ test(t => {
44
var circular = ['a', 'b'];
55
circular.push(circular);
66
t.same([circular, 'c'], [circular, 'd']);
7-
t.end();
87
});

test/fixture/es2015.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@ import test from '../../';
22

33
test(t => {
44
t.pass();
5-
t.end();
65
});

test/fixture/fail-fast.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ import test from '../../';
22

33
test(t => {
44
t.fail();
5-
t.end();
65
});
76

87
test(t => {
98
t.pass();
10-
t.end();
119
});

test/fixture/hooks-failing.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ test.beforeEach(fail);
44
test(pass);
55

66
function pass(t) {
7-
t.end();
87
}
98

109
function fail(t) {
1110
t.fail();
12-
t.end();
1311
}

test/fixture/hooks-passing.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ test.afterEach(pass);
77
test(pass);
88

99
function pass(t) {
10-
t.end();
1110
}

test/fixture/long-running.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
const test = require('../../');
33
var onExit = require('signal-exit');
44

5-
test('long running', function (t) {
5+
test.async('long running', function (t) {
66
t.plan(1);
77

88
onExit(function () {

test/fixture/loud-rejection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const test = require('../../');
22

3-
test('creates an unhandled rejection', t => {
3+
test.async('creates an unhandled rejection', t => {
44
Promise.reject(new Error(`You can't handle this!`));
55

66
setTimeout(function () {

test/fixture/one-pass-one-fail.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ const test = require('../../');
22

33
test('this is a passing test', t => {
44
t.ok(true);
5-
t.end();
65
});
76

87
test('this is a failing test', t => {
98
t.ok(false);
10-
t.end();
119
});

0 commit comments

Comments
 (0)