How can I reset the jsdom instance when using vitest in order to test a History-based router?
Asked Answered
E

1

7

I'd like to do some integration testing of my svelte + page.js-based router using vitest, but I'm running into an issue where the jsdom instance only updates correctly once per test file.

In the following setup, either test will pass when run with .only or if I split each test into its own file. But when they run in sequence, the second one will always fail. Inspecting the DOM with screen.debug() reveals that it's empty, and calls to act or tick don't seem to do anything.

I suspect it has something to do with how jsdom is interacting with the History API, but I'm not sure where to go from here.

Root.svelte

<script>
  import page from 'page'

  import SignIn from './SignIn/SignIn.svelte'
  import Upload from './Upload/Upload.svelte'
  import { authenticationToken } from './Root.stores.js'

  let currentPage

  page('/', () => {
    page.redirect('/sign-in')
  })

  page('/sign-in', () => {
    currentPage = SignIn
  })

  page('/upload', () => {
    if ($authenticationToken === null) {
      return page.redirect('/sign-in')
    }

    currentPage = Upload
  })

  page.start()
</script>

<svelte:component this={ currentPage } />

Root.svelte.test.js

import page from 'page'
import Root from './Root.svelte'
import { authenticationToken } from './Root.stores.js'

it('redirects to sign in when not authenticated', async () => {
  vi.spyOn(page, 'redirect')
  authenticationToken.set(null)

  const { act } = setupComponent(Root)
  await act(() => page('/upload'))

  expect(page.redirect).toHaveBeenCalledWith('/sign-in')
})

it('displays the upload screen when authenticated', async () => {
  authenticationToken.set('token')

  const { act } = setupComponent(Root)
  await act(() => page('/upload'))

  expect(document.getElementById('upload')).toBeInTheDocument()
})

Other Research

The issue is similar to this one in the jest project. In that issue, the recommendation was to call jsdom.reconfigure() in a beforeEach block, but I don't know how to get a hold of the jsdom instance in vitest in order to try that.

Any ideas or alternative approaches welcome, thanks!

Expiate answered 27/11, 2022 at 11:33 Comment(2)
I know this was a little while ago but I would love to know if you ever made any progress? I have a similar / related question over here: https://mcmap.net/q/1626581/-msw-react-query-vitest-requests-occurring-in-prior-test-fail-in-subsequent-test/2883500 ... I think if I could find a way to reset JSDOM window in between tests without having to move to separate files I'd be good to go.Afc
@Afc I couldn't find a solution so I am now using E2E tests for routing. 🤷🏻Expiate
H
3

Since version 1.3.0, Vitest exposes a jsdom global variable, so it should be possible to call

jsdom.reconfigure(/* ... */)

See also https://vitest.dev/config/#environment (scroll to the bottom of the section)

Holophytic answered 21/2 at 10:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.