vuejs / router

🚦 The official router for Vue.js
https://router.vuejs.org/
MIT License
3.77k stars 1.16k forks source link

Routing will not finish when clicking on router-link and the target route component is imported dynamically #2108

Closed BeniRupp closed 6 months ago

BeniRupp commented 6 months ago

Reproduction

https://github.com/BeniRupp/vue-router-async-import-bug

Steps to reproduce the bug

In a vitest test having a router with two routes, a component with a router-link and dynamic component imports for the route components:

  1. setup router in the test
  2. mount a component with a router link
  3. click on that router-link with vue-test-utils' trigger('click')
  4. wait for the route change
  5. expect the new route fullPath
const AboutView =  () => import("@/views/AboutView.vue")
// ...

it('should work', async () => {
    const router = createRouter({
        history: createWebHistory(),
        routes: [
            {path: '/', component: HomeView},
            {path: '/about', component: AboutView},
        ],
    })
    await router.push('/')
    await router.isReady()

    const wrapper = mount(
        { template: '<router-link class="link" to="/about">test</router-link>', },
        { global: { plugins: [router] }}
    )

    expect(router.currentRoute.value.fullPath).toBe('/')
    await wrapper.find('.link').trigger('click')
    await flushPromises()
    expect(router.currentRoute.value.fullPath).toBe('/about')
})

Expected behavior

The route fullPath after clicking the router-link is /about instead of /.

Actual behavior

The route fullPath is still /.

Additional information

I assume that the test will finish before the import resolves, because the router changes the route, calls the import function, but the import() statement does not resolve (see reproduction repo). Furhtermore, the click on the router-link causes a correct router beforeEach event but no afterEach event.

This problem is not reproducible if:

posva commented 6 months ago

It looks like flushPromises() isn't enough. Adding a longer wait await delay(1000) with a setTimeout, works well. You need a way to await the dynamic import in your test. This is worth asking in Vitest discussions

BeniRupp commented 6 months ago

Hi @posva, thank you for the fast response! πŸš€

Damn, I didn't test the behavior with a timeout. Thanks for the hint! This is,at least, a temporary fix. πŸ™ˆ