Skip to content

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

Closed
@lbavendanos

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

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