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

Vue.nextTick() and mocha don't play nice #7140

Closed
callumacrae opened this issue Nov 27, 2017 · 6 comments
Closed

Vue.nextTick() and mocha don't play nice #7140

callumacrae opened this issue Nov 27, 2017 · 6 comments

Comments

@callumacrae
Copy link

Version

2.5.8

Reproduction link

https://jsbin.com/lujehap/edit?html,js,output

Steps to reproduce

Run tests in repro link :)

What is expected?

Both tests should fail with similar error messages

What is actually happening?

The first test, using setTimeout, fails as expected, but with the second test, using Vue.nextTick(), just times out, with the error disappearing.


This is happening because Vue.nextTick() apparently uses a promise internally and mocha doesn't support catching unhandled promise errors.

There is a workaround, but it isn't great:

window.addEventListener('unhandledrejection', (e) => {
  throw e;
});

That at least lets you know that there was an error, but doesn't log the correct error.

You can also wrap the contents of the test in setTimeout:

it('should catch errors from Vue.nextTick()', (done) => {
  Vue.nextTick(() => {
    setTimeout(() => {
      throw new Error('test');
      done();
    });
  });
});

That will ensure that mocha knows about them.

While this is mostly a problem with mocha, I think it is unexpected that you have to handle errors inside Vue.nextTick() as if in a promise - it doesn't look like a promise from the function!

I'm not really sure what I would suggest doing about this.

@callumacrae callumacrae changed the title Vue.nextTick() eats Vue.nextTick() and mocha don't play nice Nov 27, 2017
@posva
Copy link
Member

posva commented Nov 27, 2017

Just do .catch(done); to pass the error to the done callback. But this is completely unrelated to Vue

edit: My bad, sorry. I tried to run the repro but it's missing some dependencies so I couldn't actually see it wasn't working

@posva posva closed this as completed Nov 27, 2017
@yyx990803
Copy link
Member

@posva This is somewhat related and deserves some explanation: nextTick only returns Promise when no callback is passed, here the Promise comes from the scheduler queueing, so no .catch is possible. Instead, the error is captured by Vue and sent to Vue.config.errorHandler, which if not set, simply re-throws the error.

So the correct way to deal with this is:

it('should catch errors from Vue.nextTick()', (done) => {
  Vue.config.errorHandler = done
  Vue.nextTick(() => {
    throw new Error('test');
  });
}).timeout(1000);

@callumacrae
Copy link
Author

callumacrae commented Nov 27, 2017

Sweet. I had no idea you can do that, and I had no idea that Vue.nextTick() returns a promise with no arguments (I only tried it with an argument).

I've gone with this in the end:

it('should catch errors from Vue.nextTick()', () => {
  return Vue.nextTick().then(() => {
    throw new Error('test');
  });
}).timeout(1000);

Perhaps this could use some documentation. Maybe here? Happy to send a PR.

EDIT: to clarify, all the stuff you said in your message is documented in the API docs and doesn't need improving, I just didn't know about it in the context of testing and feel it could use improvement there.

@posva
Copy link
Member

posva commented Nov 27, 2017

Yes, please do. Something that states that in order for Vue.nextTick to return a promise you have to call it without arguments could be nice IMO

@callumacrae
Copy link
Author

That's actually already in the Vue API docs, but I feel that could use improvement, too - it's pretty easy to miss that you get a promise if you don't provide any arguments unless you're looking for it.

https://vuejs.org/v2/api/#Vue-nextTick

Will send PRs to both projects soonish!

@callumacrae
Copy link
Author

PR to vuejs.org: vuejs/v2.vuejs.org#1296
PR to vue-test-utils: vuejs/vue-test-utils#207

chrisvfritz pushed a commit to vuejs/v2.vuejs.org that referenced this issue Nov 29, 2017
vuejs-jp-bot pushed a commit to vuejs-jp-bot/jp.vuejs.org that referenced this issue Nov 29, 2017
Jinjiang pushed a commit to vuejs/v2.cn.vuejs.org that referenced this issue Nov 30, 2017
kazupon pushed a commit to vuejs/jp.vuejs.org that referenced this issue Dec 3, 2017
* Added example for using .nextTick() with no arguments (#1296)

See vuejs/vue#7140

* translate
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

No branches or pull requests

3 participants