Skip to content

Commit

Permalink
[Fix] t.teardown(): ensure callback is only called once
Browse files Browse the repository at this point in the history
Fixes #551
  • Loading branch information
ljharb committed Feb 27, 2021
1 parent 50751db commit 3ea7921
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 16 deletions.
18 changes: 6 additions & 12 deletions lib/test.js
Expand Up @@ -212,34 +212,28 @@ Test.prototype._end = function (err) {
}


function next(i) {
if (i === self._teardown.length) {
function next() {
if (self._teardown.length === 0) {
completeEnd();
return;
}
var fn = self._teardown[i];
var fn = self._teardown.shift();
var res;
try {
res = fn();
} catch (e) {
self.fail(e);
}
if (res && typeof res.then === 'function') {
res.then(function () {
next(++i);
}, function (_err) {
res.then(next, function (_err) {
err = err || _err;
});
} else {
next(++i);
next();
}
}

if (this._teardown.length > 0) {
next(0);
} else {
completeEnd();
}
next();

function completeEnd() {
if (!self.ended) self.emit('end');
Expand Down
57 changes: 53 additions & 4 deletions test/teardown.js
Expand Up @@ -113,18 +113,22 @@ tap.test('teardowns', function (tt) {
);
}),
typeof Promise === 'function' ? [
'# teardown is only ever called once, even when async',
'ok ' + (11 + v.nonFunctions.length) + ' passes',
'# teardown: once?',
'# success (promise)',
'ok ' + (11 + v.nonFunctions.length) + ' should be truthy',
'ok ' + (12 + v.nonFunctions.length) + ' should be truthy',
'# success (promise) teardown: 1',
'# success (promise) teardown: 2',
'# success (promise) teardown: 3'
] : [
'# SKIP teardown is only ever called once, even when async',
'# SKIP success (promise)'
], [
'',
'1..' + ((typeof Promise === 'function' ? 1 : 0) + 10 + v.nonFunctions.length),
'# tests ' + ((typeof Promise === 'function' ? 1 : 0) + 10 + v.nonFunctions.length),
'# pass ' + ((typeof Promise === 'function' ? 1 : 0) + 5),
'1..' + ((typeof Promise === 'function' ? 2 : 0) + 10 + v.nonFunctions.length),
'# tests ' + ((typeof Promise === 'function' ? 2 : 0) + 10 + v.nonFunctions.length),
'# pass ' + ((typeof Promise === 'function' ? 2 : 0) + 5),
'# fail ' + (5 + v.nonFunctions.length),
''
]));
Expand Down Expand Up @@ -226,6 +230,18 @@ tap.test('teardowns', function (tt) {
});
});

test('teardown is only ever called once, even when async', { skip: typeof Promise !== 'function' }, function (t) {
t.plan(1);

t.teardown(function () {
t.comment('teardown: once?');
});

t.pass('passes');

return Promise.resolve();
});

test('success (promise)', { skip: typeof Promise !== 'function' }, function (t) {
t.plan(1);

Expand Down Expand Up @@ -265,3 +281,36 @@ tap.test('teardown with promise', { skip: typeof Promise !== 'function', timeout
t.end();
});
});

tap.test('teardown only runs once', { skip: typeof Promise !== 'function', timeout: 1e3 }, function (tt) {
tt.plan(1);

var test = tape.createHarness();
test.createStream().pipe(concat(function (body) {
tt.same(stripFullStack(body.toString('utf8')), [].concat(
'TAP version 13',
'# teardown is only called once, even with a plan',
'ok 1 passes',
'# Tearing down!',
'',
'1..1',
'# tests 1',
'# pass 1',
'',
'# ok',
''
));
}));

test('teardown is only called once, even with a plan', function (t) {
t.plan(1);

t.teardown(function () {
t.comment('Tearing down!');
});

t.pass('passes');

return Promise.resolve();
});
});

0 comments on commit 3ea7921

Please sign in to comment.