Tape: `Promise` support

Created on 18 Feb 2016  路  7Comments  路  Source: substack/tape

Would be great to support returning a promise to end the test when the promise is resolved.

  • It would play nice with future extensions of the language, allowing one to call tape with Async Functions to transparently return a promise.
  • It would eliminate some otherwise unfixable ordering issues with nested tests.
  • Rewriting
var test = require('tape');

test('first', function (t) {

  setTimeout(function () {
    t.ok(1, 'first test');
    t.end();
  }, 200);

  t.test('second', function (t) {
    t.ok(1, 'second test');
    t.end();
  });
});

test('third', function (t) {
  setTimeout(function () {
    t.ok(1, 'third test');
    t.end();
  }, 100);
});

to (assuming a function delay returning a Promise resolved after t milliseconds)

var test = require('tape');

test('first', async function (t) {

  await delay(200);

  t.ok(1, 'first test');

  t.test('second', async function (t) {
    t.ok(1, 'second test');
  });
});

test('third', async function (t) {
  await delay(100);
  t.ok(1, 'third test');
});

will preserve the expected order (see https://github.com/substack/tape/issues/222).


Looking at blue-tape it should be doable with something along the lines of

var ret = this._cb(this);
var self = this;
if (ret && typeof ret.then === 'function') {
  ret.then(function () {
    self.end();
  }, function (err) {
    nextTick(function () {
      throw err;
    });
  });
}

Note that it would not require a Promise library nor any configuration. Users wanting to take advantage of this feature would need to provide their own Promise implementation if necessary anyway.

Most helpful comment

@substack It's unfortunate to hold onto this callback based API, it seems to be the opposite of the direction the language is taking and its causing some weird issues. Anyway, thanks for taking the time to talk !

All 7 comments

From https://github.com/substack/tape/issues/222#issuecomment-185825192:

Supporting that is tricky because we'd have to either a) assume Promise was available, which forces the user to know they need to shim it, b) allow explicit injection of Promise so they can pass bluebird or native Promises or whatever as they like (like .setPromiseConstructor() or something), or c) add a Promise lib as a dependency.

Solution a is dangerous, b is awkward, and c is heavyweight.

The problem is that tape would need to be able to wrap test return values in Promise.resolve since it's a bad idea to do an "is this a promise" check - which means tape needs to be able to know that Promise is available.

Why would wrapping be necessary ? We don鈥檛 need any of the capabilities of well behaved promises here. The success callback could even be called on the same tick and tests would still close properly.

and if current tests return non-promise objects?

Absolutely we do need them - those capabilities (including error-catching) are part of the guarantee of promises. If the success callback is called on the same tick than a previously set-up "next tick" operation might not fire, and the test would be invalid.

Yeah I know about the guarantees promises offer but I think it's unlikely something too bad could happen here. Anyway, couldn't this behavior be namespaced under a new Test#async method to make the intent explicit ? Would it be acceptable to trust users to provide well behaved enough promises in that case ?

Doesn't tape do let errors propagate on purpose ? I'm not sure what you're meaning about error catching.

This would make tape much more complicated. A promise-oriented test library should be a separate project. Tape is a callback-oriented project. I would much rather there were 2 projects focusing on separate, clear conceptions of what they are trying to be than a single monster of a project that mixes a bunch of ideas into an incoherent mess.

@substack It's unfortunate to hold onto this callback based API, it seems to be the opposite of the direction the language is taking and its causing some weird issues. Anyway, thanks for taking the time to talk !

Time to move to promises?

Was this page helpful?
0 / 5 - 0 ratings