Skip to content

fix: use Vue Router in abstract mode #238

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

Closed

Conversation

blimmer
Copy link
Contributor

@blimmer blimmer commented Jun 23, 2021

This PR uses mode: 'abstract' when creating a Vue Router instance.

By default, the Vue Router uses 'hash' mode (docs) which, in test environments with JSDOM, updates the window.location.href hash value. In jest, the JSDOM environment is not reset between tests, which means that state appears to leak between tests, as mentioned in #210.

I did some digging through the vue-test-utils issue tracker and found vuejs/vue-test-utils#1681, which talks about this issue in more depth. The recommended solution from that thread is to use abstract mode, which guarantees you start with a clean Vue Router each time it's instantiated.

Alternately, if this solution does not seem acceptable, users can utilize a lifecycle hook, such as Jest's beforeEach to reset the state between tests. For example:

beforeEach(() => {
  window.location.replace('http://localhost/');
});

Fixes #210

@@ -39,7 +39,8 @@ function render(
const VueRouter = requiredRouter.default || requiredRouter
localVue.use(VueRouter)

router = new VueRouter({routes})
router = new VueRouter({routes, mode: 'abstract'})
router.push('/')
Copy link
Contributor Author

@blimmer blimmer Jun 23, 2021

Choose a reason for hiding this comment

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

This felt like the most reasonable default to use, since in abstract mode the stack is empty. In the default hash mode with a clean JSDOM environment, this would also be the behavior.

Alternatively, we could require the user to push their first route, but that would be a more breaking change from the existing behavior. I'm curious what the maintainer's stance on this is. Do we want to retain more compatibility with older versions of the library? Or would you prefer to leave the initial route stack to stay uninitialized for more declarative tests?

Copy link
Member

@afontcu afontcu Jun 25, 2021

Choose a reason for hiding this comment

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

Hi! First of all, thank you for tackling this one!

I think I'll take a closer look, as even though this fixes the issue, we might have some unexpected behavior here for users who would expect a regular, history-based router (not entirely sure what are the differences with abstract mode).

Maybe we could follow a similar approach to #232, where we allow users to pass their own instance of Vuex. This would allow people to set their own router mode while also preserving backwards compatibility and consistency between vuex/router options. What do you think about it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a fair point that users might expect a hash-based / history router to be used with this library. In my case, at least, having to pass the entire Vue Router would be a bit of a pain to have to do with each test, as abstract mode is the configuration I'd prefer to use throughout all my tests. So, at least initially, my thought is that some kind of global config file would be useful, for example:

// vue-testing-library.config.js
module.exports = {
  vueRouterMode: 'abstract',
};

However, it looks like other testing-library plugins don't have a global configuration file where a user could set something like this. For instance, react-testing-library has support for a custom render function (docs) where the user can set defaults.

So perhaps the way forward is to allow passing an instantiated Vue Router, but then also provide docs for a custom render function like the react-testing-library docs above? Either way, I think it also makes sense to add a point to the "FAQs" page about this, as it's a bit confusing no matter what we decide to do.

I'm happy to tackle these updates depending on the maintainer's preferences. Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

For instance, react-testing-library has support for a custom render function (docs) where the user can set defaults

We can do the same thing here at Vue Testing Lib:

import VueRouter from 'vue-router'
import MyComponent from './MyComponent'
import routes from './routes'

function customRender() {
  const router = new VueRouter({ routes, mode: 'abstract' })
  router.push('/')

  return render(MyComponent, { routes: router })
}

// and then

test('foo', () => {
  const { getByText } = customRender()
})

This would allow people to set up their custom Router's mode a single time

@blimmer
Copy link
Contributor Author

blimmer commented Jun 29, 2021

Closing in favor of #239

@blimmer blimmer closed this Jun 29, 2021
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.

Broken test isolation of VueRouter instances
2 participants