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

[QueueRunner] Support "thenables" returned by tests #1270

Closed
wants to merge 3 commits into from

Conversation

aleclarson
Copy link

@aleclarson aleclarson commented Feb 1, 2017

This commit allows done or done.fail to be called by a returned promise/thenable.

This reduces the following boilerplate:

  • promise.then(done)
  • promise.catch(done.fail)

Includes tests for resolved promises and rejected promises.
Should I include one for pending promises, too?

Example

it(() => {
  return fetch('http://www.google.com')
    .then(res => expect(res).toBe(...));
});
  • If the returned thenable is resolved, the done function is called.
  • If the returned thenable is rejected, the done.fail function is called.

Failure tests

To test failure cases, you can catch the error and call expect(error.message).

it(() => {
  return fetch('bad url')
    .catch(error => expect(error.message).toBe(...));
});

@aleclarson
Copy link
Author

Am I not allowed to use setImmediate in the tests?

@aleclarson
Copy link
Author

Fixed an edge case where the promise variable was being carried over to the next iteration, resulting in an error being thrown TypeError: promise.then is not a function.

Let me know if there are other issues. 👍

@aleclarson aleclarson changed the title [QueueRunner] Detect promises/thenables returned by queued functions [QueueRunner] Support "thenables" returned by tests Feb 25, 2017
@BenoitZugmeyer
Copy link

Disclaimer: I'm not related to Jasmine in any way, just an enthusiastic user.

This feature is quite popular and has been discussed and PR'd many times (PR #202, #681, PR #696, #923, PR #1029), and has always been rejected with the following workarounds:

  • You can just pass done and done.fail as callbacks to .then
  • If you are into coroutines, you can use jasmine-co
  • You can use jasmine-promises

In my opinion, it would be a great addition to Jasmine:

  • Most other popular test runners (mocha, jest, ava, ...) are supporting asynchronous tests via promises out of the box. It seems like a new consensus, like the done() callback a few years ago. It would help migrations from one test runner to another, and build tools/helpers compatible with multiple test runners.
  • Coroutines were alright a few years ago, but now that async/await functions are standardized and supported by Node (last stable version) and some browsers out of the box, there is not much reason to use them anymore. With support for tests returning promises, jasmine would support async functions without any extra code.
  • The jasmine-promises doesn't support nodejs (at the moment) and seems a bit abandonned to be honnest (nodejs support is on the master branch, but no release has been done for six months).
  • Adding promises support is straightforward and wouldn't add much code, and no extra dependency.

As a side note, @aleclarson : your PR breaks the CI build because of lints reported by jshint (https://travis-ci.org/jasmine/jasmine/jobs/202125138#L380)

@aleclarson
Copy link
Author

@BenoitZugmeyer Thanks for the heads up! All fixed.

I'll squash the commits once a maintainer speaks up about any nits.

Copy link
Member

@slackersoft slackersoft left a comment

Choose a reason for hiding this comment

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

In general the plan seems good for this, but there are a couple issues with the current testing strategy related browsers that don't support certain features natively.

Additionally, the build for this PR is broken for your new tests, so that would need to be fixed as well.


it("supports promises (and thenables) returned by queued functions", function(done) {
var queueableFn1 = { fn: function() {
return Promise.resolve();
Copy link
Member

Choose a reason for hiding this comment

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

Jasmine's tests need to run in IE 8+ and PhantomJS (as well as Edge, Chrome, Firefox, and Node.js) so we can't use bare Promise directly in specs for browsers that don't support them.

expect(completeCallback).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();

setImmediate(function() {
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, setImmediate isn't available in all browsers that Jasmine supports and as such can't be used in Jasmine's tests.


it("calls 'done.fail' when a promise is rejected", function(done) {
var error, queueableFn1 = { fn: function() {
return Promise.reject(error = new Error('foo'));
Copy link
Member

Choose a reason for hiding this comment

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

Native Promise as above

expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();

setImmediate(function() {
Copy link
Member

Choose a reason for hiding this comment

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

setImmediate as above

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

Successfully merging this pull request may close these issues.

None yet

3 participants