Skip to content

VTL for Vue 3: The routes option does not work correctly #195

Description

@lbavendanos

Describe the bug
When using the routes option of the render function, it throws up some warnings that have to do with the _history property and the asynchronic handling that vue router 4 has. This causes you to not be able to use the routes option correctly.

To Reproduce

import { render, screen } from '@testing-library/vue'
import '@testing-library/jest-dom'
import { defineComponent } from 'vue'
import { RouteRecordRaw } from 'vue-router'

test('Component with route', () => {
  const ComponentA = defineComponent({
    name: 'ComponentA',
    props: {
      to: {
        type: Object,
        required: true
      }
    },
    template: `<router-link :to="to" role="button">Learn More</router-link>`
  })

  const ComponentB = defineComponent({
    name: 'ComponentB'
  })

  const routeRecordRaw: RouteRecordRaw = {
    path: '/',
    name: 'componentB',
    component: ComponentB
  }

  const to = { name: routeRecordRaw.name }

  render(ComponentA, {
    props: { to },
    routes: [routeRecordRaw]
  })

  const button = screen.getByRole('button')

  expect(button).toBeInTheDocument()
  expect(button?.getAttribute('href')).toBe(routeRecordRaw.path)
})

This throws the following warning

console.warn node_modules/vue-router/dist/vue-router.cjs.js:75
    [Vue Router warn]: Unexpected error when starting the router: TypeError: Cannot read property '_history' of null

The warning is known. This is explained in the vue-test-utils v2 documentation
https://vue-test-utils.vuejs.org/v2/guide/vue-router.html#with-a-real-router

So to solve it apply what is indicated in documentation

import { render, screen } from '@testing-library/vue'
import '@testing-library/jest-dom'
import { defineComponent } from 'vue'
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

test('Component with route', async () => {
  const ComponentA = defineComponent({
    name: 'ComponentA',
    props: {
      to: {
        type: Object,
        required: true
      }
    },
    template: `<router-link :to="to" role="button">Learn More</router-link>`
  })

  const ComponentB = defineComponent({
    name: 'ComponentB'
  })

  const routeRecordRaw: RouteRecordRaw = {
    path: '/',
    name: 'componentB',
    component: ComponentB
  }

  const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes: [routeRecordRaw]
  })

  router.push('/')
  await router.isReady()

  const to = { name: routeRecordRaw.name }

  render(ComponentA, {
    props: { to },
    global: {
      plugins: [router]
    }
  })

  const button = screen.getByRole('button')

  expect(button).toBeInTheDocument()
  expect(button?.getAttribute('href')).toBe(routeRecordRaw.path)
})

Expected behavior
Be able to correctly use the routes option provided by the render function

Related information:

  • @testing-library/vue version: ^6.3.1
  • Vue version: ^3.0.0
  • node version: 14.4.0
  • npm version: 6.14.9

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions