'use strict'; var tape = require('../'); var tap = require('tap'); var concat = require('concat-stream'); var forEach = require('for-each'); var v = require('es-value-fixtures'); var inspect = require('object-inspect'); var flatMap = require('array.prototype.flatmap'); var stripFullStack = require('./common').stripFullStack; tap.test('teardowns', 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', '# success', 'ok 1 should be truthy', '# success teardown', '# success teardown 2', '# success (async)', 'ok 2 should be truthy', '# success (async) teardown', '# success (async) teardown 2', '# nested teardowns', '# nested success', 'ok 3 should be truthy', '# nested teardown (nested success level)', '# nested teardown (nested success level) 2', '# nested failure', 'not ok 4 nested failure!', ' ---', ' operator: fail', ' at: Test. ($TEST/teardown.js:$LINE:$COL)', ' stack: |-', ' Error: nested failure!', ' [... stack stripped ...]', ' at Test. ($TEST/teardown.js:$LINE:$COL)', ' [... stack stripped ...]', ' ...', '# nested teardown (nested fail level)', '# nested teardown (nested fail level) 2', '# nested teardown (top level)', '# nested teardown (top level) 2', '# fail', 'not ok 5 failure!', ' ---', ' operator: fail', ' at: Test. ($TEST/teardown.js:$LINE:$COL)', ' stack: |-', ' Error: failure!', ' [... stack stripped ...]', ' at Test. ($TEST/teardown.js:$LINE:$COL)', ' [... stack stripped ...]', ' ...', '# failure teardown', '# failure teardown 2', '# teardown errors do not stop the next teardown fn from running', 'ok 6 should be truthy', 'not ok 7 SyntaxError: teardown error!', ' ---', ' operator: fail', ' stack: |-', ' Error: SyntaxError: teardown error!', ' [... stack stripped ...]', ' ...', 'not ok 8 plan != count', ' ---', ' operator: fail', ' expected: 1', ' actual: 2', ' stack: |-', ' Error: plan != count', ' [... stack stripped ...]', ' ...', '# teardown runs after teardown error', '# teardown given non-function fails the test', 'ok 9 should be truthy', flatMap(v.nonFunctions, function (nonFunction, i) { var offset = 10; return [].concat( 'not ok ' + (offset + (i > 0 ? i + 1 : i)) + ' teardown: ' + inspect(nonFunction) + ' is not a function', ' ---', ' operator: fail', ' at: ($TEST/teardown.js:$LINE:$COL)', ' stack: |-', ' Error: teardown: ' + inspect(nonFunction) + ' is not a function', ' [... stack stripped ...]', ' at $TEST/teardown.js:$LINE:$COL', ' [... stack stripped ...]', ' at Test. ($TEST/teardown.js:$LINE:$COL)', ' [... stack stripped ...]', ' ...', i > 0 ? [] : [ 'not ok '+ (offset + 1) +' plan != count', ' ---', ' operator: fail', ' expected: 1', ' actual: 2', ' at: ($TEST/teardown.js:$LINE:$COL)', ' stack: |-', ' Error: plan != count', ' [... stack stripped ...]', ' at $TEST/teardown.js:$LINE:$COL', ' [... stack stripped ...]', ' at Test. ($TEST/teardown.js:$LINE:$COL)', ' [... stack stripped ...]', ' ...' ] ); }), typeof Promise === 'function' ? [ '# teardown is only ever called once, even when async', 'ok ' + (11 + v.nonFunctions.length) + ' passes', '# teardown: once?', '# success (promise)', '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' ? 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), '' ])); })); test('success', function (t) { t.plan(1); t.teardown(function () { t.comment('success teardown'); }); t.teardown(function () { t.comment('success teardown 2'); }); t.ok('success!'); }); test('success (async)', function (t) { t.plan(1); t.teardown(function () { t.comment('success (async) teardown'); }); t.teardown(function () { t.comment('success (async) teardown 2'); }); setTimeout(function () { t.ok('success!'); }, 10); }); test('nested teardowns', function (t) { t.plan(2); t.teardown(function () { t.comment('nested teardown (top level)'); }); t.teardown(function () { t.comment('nested teardown (top level) 2'); }); t.test('nested success', function (st) { st.teardown(function () { st.comment('nested teardown (nested success level)'); }); st.teardown(function () { st.comment('nested teardown (nested success level) 2'); }); st.ok('nested success!'); st.end(); }); t.test('nested failure', function (st) { st.plan(1); st.teardown(function () { st.comment('nested teardown (nested fail level)'); }); st.teardown(function () { st.comment('nested teardown (nested fail level) 2'); }); st.fail('nested failure!'); }); }); test('fail', function (t) { t.plan(1); t.teardown(function () { t.comment('failure teardown'); }); t.teardown(function () { t.comment('failure teardown 2'); }); t.fail('failure!'); }); test('teardown errors do not stop the next teardown fn from running', function (t) { t.plan(1); t.ok('teardown error test'); t.teardown(function () { throw new SyntaxError('teardown error!'); }); t.teardown(function () { t.comment('teardown runs after teardown error'); }); }); test('teardown given non-function fails the test', function (t) { t.plan(1); t.ok('non-function test'); forEach(v.nonFunctions, function (nonFunction) { t.teardown(nonFunction); }); }); 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); t.teardown(function () { return new Promise(function (resolve) { t.comment('success (promise) teardown: 1'); setTimeout(resolve, 10); }).then(function () { t.comment('success (promise) teardown: 2'); }); }); t.teardown(function () { t.comment('success (promise) teardown: 3'); }); setTimeout(function () { t.ok('success!'); }, 10); }); }); tap.test('teardown with promise', { skip: typeof Promise !== 'function', timeout: 1e3 }, function (tt) { tt.plan(2); tape('dummy test', function (t) { var resolved = false; t.teardown(function () { tt.pass('tape teardown'); var p = Promise.resolve(); p.then(function () { resolved = true; }); return p; }); t.on('end', function () { tt.is(resolved, true); }); 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(); }); });