Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support use of t.end as callback. #181

Closed
wants to merge 1 commit into from

Conversation

timoxley
Copy link
Contributor

  • Binds all Test.prototype methods to current test.
  • Checks for truthy error as first argument to Test.prototype.end.

Closes #180.

@@ -134,7 +138,11 @@ Test.prototype.run = function () {
}.bind(this));
};

Test.prototype.end = function () {
Test.prototype.end = function (err) {
if (arguments.length >= 1 && Boolean(err)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (arguments.length >= 1 && err) {?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just if (err) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah wtf am I doing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally this was !!err but linter told me to Boolean(err) so I followed blindly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@sindresorhus
Copy link
Member

Looks good to me. @vdemedes @jamestalmage ?

Test.prototype.end = function () {
Test.prototype.end = function (err) {
if (arguments.length >= 1 && Boolean(err)) {
this.ifError(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they've used t.plan(), won't this increase their assertion count causing a plan error message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you have a plan and call t.end?

@vadimdemedes
Copy link
Contributor

Except suggestions in comments, everything is good.

* Binds all Test.prototype methods to current test.
* Checks for truthy error as first argument to Test.prototype.end.

Closes avajs#180.
@@ -134,7 +138,11 @@ Test.prototype.run = function () {
}.bind(this));
};

Test.prototype.end = function () {
Test.prototype.end = function (err) {
if (arguments.length >= 1 && err) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still genuinely curious why you are checking argument length.
If arguments.length === 0, isn't err going to be falsy no matter what?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea is to only log the assertion if there's some arguments passed. Alternative is have every test log an additional ifError assertion at the end.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I'm saying

if (err) {
  this.ifError(err)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it should always log the assertion if there's arguments.length? i.e. intent is to use as errback handler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.

We need it to behave consistently whether or not it's being used as a callback

t.plan(1);
t.ok(true);
t.end();

should perform the same as

t.plan(1)
t.ok(true);
setImmediate(t.end);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in neither of those situations will the t.end be called with any arguments though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use-case I'm thinking about goes something like this:

test(t => {
    fs.readFile('data.txt', t.end);
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is fine, but for your plan test do something that is not async:

test(t => {
    t.plan(1);
    t.ok(true);
    t.end(new Error('something bad happened'));
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid conflicts with t.plan(), this.ifError(err) could be replaced with:

this.assertError = new assert.AssertionError({
  actual: err,
  message: 'Callback called with an error → ' + err,
  operator: 'callback'
});

this.exit();

This is the same stuff we do when promise rejects.

@timoxley
Copy link
Contributor Author

Also note we're opting for checking & printing error before checking if .end has been called more than once. This is how tape does it and I think it makes sense as the error message + stack is going to be more helpful messaging than simply 'called end more than once'. They'll get this message too, but only after they fix the actual source of the error.

@jamestalmage
Copy link
Contributor

What happens if you have a plan and call t.end?

I don't know, but we probably should have a test for it.

@jamestalmage
Copy link
Contributor

@timoxley looking at the code again I'm pretty sure you are going to get a bad error message if you use plan and end with this.

Please write a test that does this:

test(t => {
  t.plan(1);
  t.ok(1);
  t.end(new Error('you should get this error message, not a plan count error'));
});

And check the message of the thrown exception.

@jamestalmage
Copy link
Contributor

@timoxley I think it's down to that one if statement and another test ensuring your use of ifError does not generate a plan count error message.

@vadimdemedes
Copy link
Contributor

Hey @timoxley, could you please fix this suggestion (#181 (diff)), so that we can merge it in? Thanks!

@vadimdemedes
Copy link
Contributor

Closed via 403a28c

Thanks @timoxley!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants