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

Async pending fails the spec when used with Promises #1450

Closed
slackersoft opened this issue Nov 17, 2017 · 16 comments
Closed

Async pending fails the spec when used with Promises #1450

slackersoft opened this issue Nov 17, 2017 · 16 comments
Labels

Comments

@slackersoft
Copy link
Member

The work done to handle global errors in async specs using the done callback correctly collects the pending exception and marks the spec appropriately. When calling pending from within a Promise returned by a spec, it is treated as a Promise failure and doesn't mark the spec as pending.

Example suite:

it('done pends', function(done) {
  setTimeout(pending, 10);
});

it('promise pends', function() {
  return new Promise(function () {
    pending('promise');
  });
});

Output:

npm test

> tester@ test /Users/gregg/workspace/tester
> jasmine --config=jasmine.json

Started
*F

Failures:
1) promise pends
  Message:
    Failed: => marked Pendingpromise
  Stack:
    Error: Failed: => marked Pendingpromise
        at runMicrotasksCallback (internal/process/next_tick.js:58:5)
        at _combinedTickCallback (internal/process/next_tick.js:67:7)
        at Immediate._tickCallback (internal/process/next_tick.js:98:9)
        at runCallback (timers.js:651:20)
Pending:

1) done pends
  No reason given

2 specs, 1 failure, 1 pending spec
Finished in 0.022 seconds

Possible Solution

It looks like the Spec object only checks for the isPendingSpecException when handling an exception, but the QueueRunner passes Promise failures along via fail which causes them to skip this logic and go directly to the expectation failure handler.

The goal of using fail in QueueRunner was to not have to duplicate the continuation logic, but it probably needs to change to handle a Promise rejection as an Error and then continue on after that.

Your Environment

  • Version used: jasmine 2.8
  • Environment name and version nodejs v7.5.0 (and others)

We would be happy to review a pull request that addresses this issue.

@slackersoft
Copy link
Member Author

Similar to #1449

@rasjani
Copy link

rasjani commented Nov 30, 2017

I spend a few hours yesterday reading the code around this issue and looking into possible way fix this issue.

Essentially the issue can be caught within QueueRunner's atttach() at:

         if (maybeThenable && j$.isFunction_(maybeThenable.then)) {
            maybeThenable.then(next, next.fail);
            completedSynchronously = false;
            return { completedSynchronously: false };
          }

maybeThenable is called and if promise fails, it goes to next.fail() - Now, if someone could point out how i could get a reference to running Spec from that point on so that i could mark it pending would be nice. As, just comparing the error in next.fail() to pending i'm already able to prevent the actual error but reporting the spec as pending wont happen..

@slackersoft
Copy link
Member Author

@rasjani this should be fixed on master now. If you have a chance, please take a look and if you're still seeing the issue with the updated code let us know.

Thanks for using Jasmine!

@fushi
Copy link

fushi commented Jan 30, 2018

@slackersoft Is this supposed to fix angular/jasminewd#32 as well?

@sgravrock
Copy link
Member

@fushi That's likely to have been already working for a release or four, depending on exactly what flavor of async spec we're talking about.

@fushi
Copy link

fushi commented Jan 30, 2018

@sgravrock I'm using Protractor/Jasmine, and still hitting this issue with:

it('Should be pending', () => { pending(); });

Which fails like this:

Failed: => marked Pending

@slackersoft
Copy link
Member Author

This functionality should have been released in Jasmine 2.9. You'll have to make sure your Protractor is using the newest version of Jasmine to get this fix.

@jasmine4ever
Copy link

@slackersoft Is there a way to programmatically find if the pending() is called in a spec? Or if the error object contains any details regarding the pending?

@slackersoft
Copy link
Member Author

Since pending() is invoked during execution of a spec, there isn't really a good way to determine that it will have been called once the spec will have completed. If Jasmine is handling the error, it should properly mark the spec as pending and add any message to the result passed to reporters. If you are injecting a different handler that is catching the error that is thrown, you should be able to look at the message to determine if it is the pending spec exception.

Hope this helps. Thanks for using Jasmine!

@jasmine4ever
Copy link

@slackersoft Yes, I am passing a custom handler. How can I get an error message? Is there a specific function in jasmine to do that? Can I programmatically set a spec to pending if I see Pending string in the thrown error string? If yes, how? Any help with that?

@slackersoft
Copy link
Member Author

@jasmine4ever this seems to have move quite far away from the original intent in this issue. Please start a new conversation with some more specifics on your actual use case. This probably belongs on the jasmine-js group, since this sounds more like a "how do I?" question, than an issue with Jasmine itself.

Thanks for using Jasmine!

@jasmine4ever
Copy link

Didn't knew about the group. Will start a thread there. Thank you.

@ViieeS
Copy link

ViieeS commented Apr 5, 2019

I have the latest version of Jasmine v3.3.0 and get error when calling pending()... 😕

@slackersoft
Copy link
Member Author

@ViieeS, please open a new issue and provide us with some more information about what you're seeing.

@shadiabuhilal
Copy link

shadiabuhilal commented May 27, 2021

To skip test block programmatically, please use done arg, and call done function before calling pending.

example:

it('promise pends', function(done) {
  return new Promise(function () {
    // Make sure to call done() before pending()
    done();
    pending('promise');
  });
});

@sgravrock
Copy link
Member

This spec isn't correct:

it('promise pends', function(done) {
  return new Promise(function () {
    // Make sure to call done() before pending()
    done();
    pending('promise');
  });
});

It does two different things that Jasmine doesn't support: It both takes a callback and returns a promise, and it runs more code after it signals completion. Depending on the exact version of Jasmine in use it might appear to work correctly, it might pend the wrong spec, it might trigger a failure, or it might misbehave in other ways.

In any case, there shouldn't be a need for workarounds like that. This bug has been fixed for 3.5 years now. If anyone is still unable to make a promise-returning spec pend by simply calling pending(), please log a new issue with enough information to reproduce it rather than commenting here. (Or if you're still on Jasmine <2.9.0, please upgrade.)

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

No branches or pull requests

7 participants