Skip to content

Commit

Permalink
Teardowns run in reverse order
Browse files Browse the repository at this point in the history
Fixes #2516.
  • Loading branch information
novemberborn committed Feb 7, 2021
1 parent bcb750c commit dc4483f
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 31 deletions.
4 changes: 2 additions & 2 deletions docs/02-execution-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ Plan how many assertions there are in the test. The test will fail if the actual

## `t.teardown(fn)`

Registers the `fn` function to be run after the test has finished. You can register multiple functions and they'll run in order<sup>†</sup>. You can use asynchronous functions: only one will run at a time.
Registers the `fn` function to be run after the test has finished. You can register multiple functions. In AVA 3 the functions are called in order, but in AVA 4 they'll run in _reverse_ order.<sup>†</sup>. You can use asynchronous functions: only one will run at a time.

You cannot perform assertions using the `t` object or register additional functions from inside `fn`.

You cannot use `t.teardown()` in hooks either.

<sup>†</sup> In the next major release we'll change this so teardown functions run in reverse order. The last registered function will be called first. You can opt in to this behavior now by enabling the `reverseTeardowns` experiment.
<sup>†</sup> You can opt in to this behavior in AVA 3 by enabling the `reverseTeardowns` experiment.

**`package.json`**:

Expand Down
1 change: 0 additions & 1 deletion lib/load-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const NO_SUCH_FILE = Symbol('no ava.config.js file');
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
const EXPERIMENTS = new Set([
'nextGenConfig',
'reverseTeardowns',
'sharedWorkers'
]);

Expand Down
6 changes: 1 addition & 5 deletions lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,7 @@ class Test {
}

async runTeardowns() {
const teardowns = [...this.teardowns];

if (this.experiments.reverseTeardowns) {
teardowns.reverse();
}
const teardowns = [...this.teardowns].reverse();

for (const teardown of teardowns) {
try {
Expand Down
30 changes: 7 additions & 23 deletions test-tap/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const sinon = require('sinon');
const delay = require('delay');
const snapshotManager = require('../lib/snapshot-manager');
const Test = require('../lib/test');
const {ava, withExperiments} = require('./helper/ava-test');
const {ava} = require('./helper/ava-test');

const failingTestHint = 'Test was expected to fail, but succeeded, you should stop marking the test as failing';

Expand Down Expand Up @@ -815,30 +815,14 @@ test('teardown awaits promise', t => {
});
});

test('teardowns run sequentially in order', t => {
const teardownA = sinon.stub().resolves(delay(200));
let resolveB;
const teardownB = sinon.stub().returns(new Promise(resolve => {
resolveB = resolve;
}));
return ava(a => {
a.teardown(() => teardownA().then(resolveB));
a.teardown(teardownB);
a.pass();
}).run().then(result => {
t.is(result.passed, true);
t.ok(teardownA.calledBefore(teardownB));
});
});

test('teardowns run in reverse order when the `reverseTeardowns` experimental feature is enabled', t => {
test('teardowns run in reverse order', t => {
let resolveA;
const teardownA = sinon.stub().returns(new Promise(resolve => {
resolveA = resolve;
}));
const teardownB = sinon.stub().resolves(delay(200));

return withExperiments({reverseTeardowns: true})(a => {
return ava(a => {
a.teardown(teardownA);
a.teardown(() => teardownB().then(resolveA));
a.pass();
Expand Down Expand Up @@ -896,9 +880,9 @@ test('teardown errors are hidden behind assertion errors', t => {
});
});

test('teardowns errors do not stop next teardown from running', t => {
const teardownA = sinon.stub().throws('TeardownError');
const teardownB = sinon.spy();
test('teardown errors do not stop next teardown from running', t => {
const teardownA = sinon.spy();
const teardownB = sinon.stub().throws('TeardownError');
return ava(a => {
a.teardown(teardownA);
a.teardown(teardownB);
Expand All @@ -908,7 +892,7 @@ test('teardowns errors do not stop next teardown from running', t => {
t.is(result.error.name, 'TeardownError');
t.ok(teardownA.calledOnce);
t.ok(teardownB.calledOnce);
t.ok(teardownA.calledBefore(teardownB));
t.ok(teardownB.calledBefore(teardownA));
});
});

Expand Down

0 comments on commit dc4483f

Please sign in to comment.