testing-library / user-event

🐕 Simulate user events
https://testing-library.com/user-event
MIT License
2.17k stars 244 forks source link

When I run the tests together they break, but when I run them one by one they work normally #798

Closed marcosapj2 closed 2 years ago

marcosapj2 commented 2 years ago

Relevant code or config

import PokemonList from '../'
import { render, screen, waitFor } from '@test-utils'
import { setupServer } from 'msw/node'
import userEvent from '@testing-library/user-event'
import listPokemonHandler from '@mocks/handlers/listPokemons'
import pokemonsMock from '@mocks/objects/pokemons.json'

describe('PokemonList', () => {
  const server = setupServer(listPokemonHandler)

  beforeAll(() => {
    server.listen()
  })

  afterEach(() => server.resetHandlers())
  afterAll(() => server.close())

  it('should change items when search', async () => {
    render(<PokemonList />)

    const input = screen.getByRole('textbox')

    userEvent.type(input, 'per') // This event is being fired in the test below

    await waitFor(() => {
      expect(screen.queryByText('Peraxoq')).toBeInTheDocument()
      expect(screen.queryByText('Peris')).toBeInTheDocument()
      expect(screen.queryByText('Pikalu')).not.toBeInTheDocument()
    })
  })

  it('should render the list of pokemons', async () => { // The two tests when I run them separately using `it.only` it works
    render(<PokemonList />) // Here I should have a list of 6 items, but I'm getting the result of a search with the text 'per'

    const lastPokemonOnFirstPage = pokemonsMock.results[5]

    await waitFor(() => {
      expect(screen.queryByText(lastPokemonOnFirstPage.name)).toBeInTheDocument()
    })
  })
})

What you did: react-app-rewired test PokemonList What happened:

The tests are breaking, bringing the following feedback: ```javascript FAIL src/containers/PokemonList/__tests__/PokemonList.test.tsx (8.03 s) PokemonList √ should change items when search (741 ms) × should render the list of pokemons (1041 ms) ● PokemonList › should render the list of pokemons expect(received).toBeInTheDocument() received value must be an HTMLElement or an SVGElement. Received has value: null

    VR Pokedex

  • Peris

    Peris

  • Peraxoq

    Peraxoq

36 | 37 | await waitFor(() => { > 38 | expect(screen.queryByText(lastPokemonOnFirstPage.name)).toBeInTheDocument() | ^ 39 | }) 40 | }) 41 | }) at __EXTERNAL_MATCHER_TRAP__ (node_modules/expect/build/index.js:342:30) at Object.toBeInTheDocument (node_modules/expect/build/index.js:343:15) at src/containers/PokemonList/__tests__/PokemonList.test.tsx:38:63 at runWithExpensiveErrorDiagnosticsDisabled (node_modules/@testing-library/dom/dist/config.js:51:12) at checkCallback (node_modules/@testing-library/dom/dist/wait-for.js:127:77) at checkRealTimersCallback (node_modules/@testing-library/dom/dist/wait-for.js:119:16) at Timeout.task [as _onTimeout] (node_modules/jsdom/lib/jsdom/browser/Window.js:516:19) ```

Reproduction repository: https://github.com/marcosapj2/vrpokedex

Problem description: When I run the tests together they break, but when I run them one by one they work normally. What is happening is that the "userEvent.type(input, 'per')" shown above is somehow affecting the other test, causing the request return wrong

Suggested solution: I don't know yet, I thought the cleanup would help but it already happens automatically

marcosapj2 commented 2 years ago

The print of the tests running separately:

first test
second test
ph-fritsche commented 2 years ago

You're global state change per react-redux is bleeding into the other test. This is either because you don't reset it properly or because your debounced state changes happen during the next test.