Search code examples
reactjsunit-testingtestingreact-testing-libraryvitest

Vitest testing library userEvent - TypeError: element.ownerDocument.getSelection is not a function


When using fireEvent from @testing-library/react tests are passing and everything is fine.
I am trying to use @testing-library/user-event, which the testing-library docs recommend using, but after changing the click event to await user.click() the tests fail with the following error:

TypeError: element.ownerDocument.getSelection is not a function

I am wondering if it is a vitest problem and I should stick to the fireEvent api, or I am simply missing something.

The test code:

import { vi } from 'vitest';
import { fireEvent, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import renderWithProviders from 'utils/renderWithProviders';
import QuantityInput from '.';

describe('when decrement button is clicked', () => {
  it('should decrement if count is greater than minCount', async () => {
    const setCountMock = vi.fn();
    const user = userEvent.setup();
    renderWithProviders(<QuantityInput count={3} minCount={2} setCount={setCountMock} />);
    await user.click(screen.getByLabelText('Decrease quantity'));
    // fireEvent.click(screen.getByLabelText('Decrease quantity'));
    expect(setCountMock).toHaveBeenCalledTimes(1);
    expect(setCountMock).toHaveBeenCalledWith(2);
  });
});

My package.json:

{
  "name": "ecommerce",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "test": "vitest"
  },
  "dependencies": {
    "@hookform/resolvers": "^3.0.0",
    "@reduxjs/toolkit": "^1.9.3",
    "classnames": "^2.3.2",
    "cross-fetch": "^3.1.6",
    "firebase": "^9.18.0",
    "msw": "^1.2.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.43.7",
    "react-icons": "^4.8.0",
    "react-loader-spinner": "^5.3.4",
    "react-redux": "^8.0.5",
    "react-router-dom": "^6.9.0",
    "tailwindcss": "^3.3.2",
    "vite-tsconfig-paths": "^4.0.7",
    "zod": "^3.21.4"
  },
  "devDependencies": {
    "@testing-library/dom": "^9.2.0",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@typescript-eslint/eslint-plugin": "^5.55.0",
    "@typescript-eslint/parser": "^5.55.0",
    "@vitejs/plugin-react": "^3.1.0",
    "autoprefixer": "^10.4.14",
    "eslint": "^8.2.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-airbnb-typescript": "^17.0.0",
    "eslint-config-prettier": "^8.7.0",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-jsx-a11y": "^6.5.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.28.0",
    "eslint-plugin-react-hooks": "^4.3.0",
    "postcss": "^8.4.21",
    "prettier": "^2.8.6",
    "prettier-plugin-tailwindcss": "^0.2.5",
    "typescript": "^4.9.3",
    "vite": "^4.2.0",
    "vitest": "^0.29.8"
  }
}


Solution

  • try to add a jest environment directive in the top of your test files. @jest-environment jsdom

    /**
     * @jest-environment jsdom
     */
    
    import { vi } from 'vitest';
    import { fireEvent, screen } from '@testing-library/react';
    import userEvent from '@testing-library/user-event';
    import renderWithProviders from 'utils/renderWithProviders';
    import QuantityInput from '.';
    
    describe('when decrement button is clicked', () => {
      it('should decrement if count is greater than minCount', async () => {
        const setCountMock = vi.fn();
        const user = userEvent.setup();
        renderWithProviders(<QuantityInput count={3} minCount={2} setCount={setCountMock} />);
        await user.click(screen.getByLabelText('Decrease quantity'));
        // fireEvent.click(screen.getByLabelText('Decrease quantity'));
        expect(setCountMock).toHaveBeenCalledTimes(1);
        expect(setCountMock).toHaveBeenCalledWith(2);
      });
    });