Skip to content

Expose RouterLink and RouterView components #1976

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
eddyerburgh opened this issue Jan 9, 2018 · 12 comments
Closed

Expose RouterLink and RouterView components #1976

eddyerburgh opened this issue Jan 9, 2018 · 12 comments

Comments

@eddyerburgh
Copy link
Member

What problem does this feature solve?

Currently it's not possible to find RouterLink and RouterView when using vue-test-utils. You can find the rendered content, but if you want to check that a RouterLink receives the correct to property, you need to check the tag renders an href:

wrapper.find('a').element.href

We're considering adding a RouterLink stub to vue-test-utils, so you can do this:

wrapper.find(RouterLink).props().to

But adding a stub basically means reimplimenting the RouterLink, since we don't actually need to stub it, we just need to have access to the component as a selector.
Instead, would we be able to expose RouterLink and RouterView from Vue Router?

What does the proposed API look like?

We could import the components with the same name they are registered with:

import { RouterLink, RouterView } from 'vue-router'
@JounQin
Copy link
Contributor

JounQin commented Jan 9, 2018

Why not use Vue.component to attach them?

const RouterView = Vue.component('router-view');
const RouterLink = Vue.component('router-link');

@eddyerburgh
Copy link
Member Author

@JounQin I didn't know you could use Vue component like that.

The problem is you need Vue Router installed on the Vue instance, which adds $route and $router as read-only values. So instead, you'd have to do something like this:

const localVue = createLocalVue()
localVue.use(VueRouter)
const RouterLink = localVue.component('router-link');

const wrapper = shallow(Comp, { localVue })
wrapper.find(RouterLink).props().to

Which I suppose isn't too bad 🤔

@LinusBorg
Copy link
Member

@eddyerburgh I "not too bad" good enough to close this? :-P

@eddyerburgh
Copy link
Member Author

I think we still need the change for two reasons:

  1. If you install Vue Router you can't mock $route or $router in a test, so you wouldn't be able to test a RouterLink component and mock the param value of $route.
  2. We'd need to make users aware that they need to follow this pattern (installing VueRouter then calling Vue.component to access to RouterLink component). If we expose RouterLink and RouterView, users will be able to follow the recommended pattern for finding stubbed components

@posva
Copy link
Member

posva commented Jan 10, 2018

Looks good to me and it's very easy to add. What do you think? @yyx990803

@yyx990803
Copy link
Member

I think that's good to have. Open to PR.

@eddyerburgh
Copy link
Member Author

This would be a breaking change for the common js or browser build.

We can export them in vue-test-utils instead

@ArmorDarks
Copy link

It would be so much better if we could avoid Router injecting global router-link component and instead import it explicitly whenever it is needed with import Link from 'vue-router/link'.

That way we will have self-contained components. Right now they are relying on obscure globally injected component, which you need to re-added during tests by using whole router instance, instead of declaring it imports at first place — in the component itself.

@niksy
Copy link

niksy commented Sep 29, 2018

I suppose this is rejected and we should follow #1976 (comment)?

@graup
Copy link

graup commented Jul 2, 2019

@ArmorDarks made a good case for this. I also just ran into this issue. Our component library, using its own set of node_modules, uses a different Vue instance which doesn't have the component. Being able to explicitly import it would solve this issue.

This seems like a simple non-breaking change.

@eddyerburgh @yyx990803

@graup
Copy link

graup commented Jul 17, 2019

Here's a tentative PR: #2853

As mentioned by @eddyerburgh, we can't add additional exports to the umd/browser builds because they only support a single default export. We can however add them to the ES module builds without breaking backwards compatibility. I assume anyone interested in this feature is using ES modules anyway. I concede that it is a bit hacky though.

@graup
Copy link

graup commented Jul 17, 2019

Finally, I am also convinced that this is not needed in vue-router. Here's the summary:

  • You can use Vue.component to get a reference to the components:
const RouterView = Vue.component('router-view');
const RouterLink = Vue.component('router-link');

Case closed, as far as I can tell.

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

No branches or pull requests

8 participants