typescriptnext.jsjestjsreact-testing-library

How can one test Chakra v3 UI Select in NextJS with Jest?


I'm building a NextJS (react) app with Chakra UI (version 3). I'd like to write unit tests, but I don't know to handle the way Chakra UI v3 handles select.

Here's a sample test app:

'use client';

import { createListCollection, Select, VStack } from '@chakra-ui/react';
import { useEffect, useRef, useState } from 'react';

const sizeList = createListCollection({
  items : [
    { value: '10', label: '10' },
    { value: '15', label: '15' },
    { value: '20', label: '20' },
    { value: '30', label: '30' },
    { value: '50', label: '50' },
    { value: '75', label: '75' },
    { value: '100', label: '100' },
    { value: '150', label: '150' },
    { value: '250', label: '250' },
  ],
  itemToString: (item) => `${item.label}`,
  itemToValue: (item) => item.value
}) ;

export default function Page() {

  const [currentSize, setCurrentSize] = useState(50);
  const sizeChooserRef = useRef<HTMLSelectElement>(null);

  useEffect(() => {
    const sizeChooser = sizeChooserRef.current;
    if (sizeChooser === null) return;
    const updateCurrentSize = () => {
      const newSize = parseInt(sizeChooser.value);
      if (newSize > 0) {
        setCurrentSize(newSize);
      }
    }
    sizeChooser.addEventListener('change', updateCurrentSize);
    updateCurrentSize(); // Set initial size based on the default value
    return () => {
      sizeChooser.removeEventListener('change', updateCurrentSize);
    };
  }, [sizeChooserRef]);
 
 

  return (
    <div>
      <VStack alignItems="center">
        <Select.Root defaultValue={["50"]} collection={sizeList}>
          <Select.Label>Choose a size</Select.Label>
          <Select.HiddenSelect ref={sizeChooserRef} />
          <Select.Control>
            <Select.Trigger>
              <Select.ValueText placeholder="select size" />
            </Select.Trigger>
          </Select.Control>
          <Select.Positioner>
            <Select.Content>
              {sizeList.items.map((item) => (
                <Select.Item item={item} key={item.label}>
                  {item.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select.Positioner>
        </Select.Root>
        <span>Current size: {currentSize}</span>
      </VStack>
    </div>
  );
  
}

Notice how Select.HiddenSelect is necessary because otherwise there is no place to put the ref attribute. This code works as expected. No problems so far.

Now here are the tests I try to write:

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import Page from './page';
import { Provider } from '@/components/ui/provider';
import userEvent from '@testing-library/user-event';

function chakraRender(x : JSX.Element) {
    return render(<Provider>{x}</Provider>);
}

describe ('Page has required parts', () => {
    test('renders size selector label', () => {
        chakraRender(<Page />);
        const sizeSelectorElement = screen.getByRole('combobox',{name:/Choose a size/});
        expect(sizeSelectorElement).toBeInTheDocument();
    });

    test('select an option #1', async () => {
        const user = userEvent.setup();
        chakraRender(<Page />);
        const sizeSelector = screen.getByRole('combobox', {name: /Choose a size/i });
        await user.selectOptions(sizeSelector, "75");
        expect(sizeSelector).toHaveValue('75');
    });
});

The first test works fine. It finds the combo box and it's in the document, but the second test fails miserably. selectOptions doesn't work -- I suspect because Chakra has converted the select into a button which doesnt include the options as sub-elements. Heres the error from Jest:

$ npm run test -- --verbose

> test
> jest --verbose

 FAIL  app/page.test.tsx
  Page has required parts
    ✓ renders size selector label (183 ms)
    ✕ select an option #1 (69 ms)

  ● Page has required parts › select an option #1

    TestingLibraryElementError: Value "75" not found in options

    Ignored nodes: comments, script, style
    <button
      aria-controls="select::r1::content"
      aria-expanded="false"
      aria-haspopup="listbox"
      aria-labelledby="select::r1::label"
      class="chakra-select__trigger css-1hl2915"
      data-part="trigger"
      data-scope="select"
      data-state="closed"
      dir="ltr"
      id="select::r1::trigger"
      role="combobox"
      type="button"
    >
      <span
        class="chakra-select__valueText css-176t9sc"
        data-part="value-text"
        data-scope="select"
        dir="ltr"
      >
        50
      </span>
    </button>

      20 |         chakraRender(<Page />);
      21 |         const sizeSelector = screen.getByRole('combobox', {name: /Choose a size/i });
    > 22 |         await user.selectOptions(sizeSelector, "75");
         |                    ^
      23 |         expect(sizeSelector).toHaveValue('75');
      24 |     });
      25 |

      at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)
      at node_modules/@testing-library/user-event/dist/cjs/utility/selectOptions.js:39:39
          at Array.map (<anonymous>)
      at Object.selectOptionsBase (node_modules/@testing-library/user-event/dist/cjs/utility/selectOptions.js:31:38)
      at Object.selectOptions (node_modules/@testing-library/user-event/dist/cjs/utility/selectOptions.js:18:30)
      at node_modules/@testing-library/user-event/dist/cjs/setup/setup.js:85:45
      at Object.asyncWrapper (node_modules/@testing-library/react/dist/pure.js:88:28)
      at Object.wrapAsync (node_modules/@testing-library/user-event/dist/cjs/setup/wrapAsync.js:8:28)
      at Object.method [as selectOptions] (node_modules/@testing-library/user-event/dist/cjs/setup/setup.js:85:26)
      at Object.selectOptions (app/page.test.tsx:22:20)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        1.824 s, estimated 2 s
Ran all test suites.

For reference, here is my package.json

{
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "jest",
    "test:ci": "jest --ci"
  },
  "dependencies": {
    "@chakra-ui/react": "^3.8.1",
    "@emotion/react": "^11.14.0",
    "next": "latest",
    "next-themes": "^0.4.4",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-icons": "^5.5.0",
    "server-only": "^0.0.1"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "6.1.5",
    "@testing-library/react": "^15.0.7",
    "@testing-library/user-event": "^14.6.1",
    "@types/jest": "29.5.11",
    "@types/jsdom": "^20.0.0",
    "@types/react": "18.2.45",
    "eslint": "9.21.0",
    "eslint-config-next": "15.2.0",
    "jest": "29.7.0",
    "jest-environment-jsdom": "29.7.0",
    "jsdom": "^20.0.0",
    "nanoid": "^3.3.8",
    "node-mocks-http": "^1.16.2",
    "ts-node": "^10.9.2",
    "typescript": "5.3.3"
  }
}

I tried using click instead of selectOptions to see if it would bring up a menu or some sort that could be selected from, but this was a disaster:

$ npm run test -- --verbose

> test
> jest --verbose

  console.error
    [Error: Uncaught [ReferenceError: ResizeObserver is not defined]] {
      detail: ReferenceError: ResizeObserver is not defined
          at Object.autoUpdate (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@floating-ui/dom/dist/floating-ui.dom.umd.js:773:7)
          at getPlacementImpl (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/popper/dist/index.js:259:52)
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/popper/dist/index.js:274:21
          at invokeTheCallbackFunction (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jsdom/lib/jsdom/living/generated/Function.js:19:26)
          at runAnimationFrameCallbacks (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jsdom/lib/jsdom/browser/Window.js:603:13)
          at Timeout._onTimeout (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jsdom/lib/jsdom/browser/Window.js:581:11)
          at listOnTimeout (node:internal/timers:581:17)
          at processTimers (node:internal/timers:519:7),
      type: 'unhandled exception'
    }

      at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:63:23)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
      at runAnimationFrameCallbacks (node_modules/jsdom/lib/jsdom/browser/Window.js:605:13)
      at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/browser/Window.js:581:11)

  console.error
    Error: Uncaught [TypeError: dom.getContentEl(...)?.scrollTo is not a function]
        at Array.forEach (<anonymous>)
        at new Promise (<anonymous>) {
      detail: TypeError: dom.getContentEl(...)?.scrollTo is not a function
          at scrollContentToTop (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/select/dist/index.js:978:37)
          at Machine.executeActions (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/core/dist/index.js:469:13)
          at Machine.performExitEffects (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/core/dist/index.js:550:12)
          at Machine.stop (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/core/dist/index.js:261:12)
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@zag-js/react/dist/index.js:170:15
          at safelyCallDestroy (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:22971:5)
          at commitDeletionEffectsOnFiber (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24142:23)
          at recursivelyTraverseDeletionEffects (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24028:5)
cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24028:5)
          at commitDeletionEffectsOnFiber (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24157:9)
          at commitDeletionEffects (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24015:5)
          at recursivelyTraverseMutationEffects (/home/boyland/Documents/Courses/sp25-
...
cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24298:9)
          at commitMutationEffectsOnFiber (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24471:9)
          at commitMutationEffects (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:24282:3)
          at commitRootImpl (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:26849:5)
          at commitRoot (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:26721:5)
          at performSyncWorkOnRoot (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:26156:3)
          at flushSyncCallbacks (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:12042:22)
          at flushSync (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:26240:7)
          at ReactDOMRoot.Object.<anonymous>.ReactDOMHydrationRoot.unmount.ReactDOMRoot.unmount [as unmount] (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react-dom/cjs/react-dom.development.js:29375:5)
          at Object.unmount (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/pure.js:155:12)
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/pure.js:286:12
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/act-compat.js:48:24
          at act (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/react/cjs/react.development.js:2512:16)
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/act-compat.js:47:25
          at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/pure.js:285:28
          at Array.forEach (<anonymous>)
          at cleanup (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/pure.js:281:22)
          at Object.<anonymous> (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@testing-library/react/dist/index.js:28:25)
          at Promise.then.completed (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/utils.js:298:28)
          at new Promise (<anonymous>)
          at callAsyncCircusFn (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/utils.js:231:10)
          at _callCircusHook (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/run.js:281:40)
          at runNextTicks (node:internal/process/task_queues:60:5)
          at listOnTimeout (node:internal/timers:545:9)
          at processTimers (node:internal/timers:519:7)
          at _runTest (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/run.js:254:5)
          at _runTestsForDescribeBlock (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/run.js:126:9)
          at _runTestsForDescribeBlock (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/run.js:121:9)
          at run (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/run.js:71:3)
          at runAndTransformResultsToJestFormat (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)
          at jestAdapter (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)
          at runTestInternal (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-runner/build/runTest.js:367:16)
          at runTest (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/jest-runner/build/runTest.js:444:34),
      type: 'unhandled exception'
    }

      at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:63:23)
      at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:353:9)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
      at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9)
      at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17)
      at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34)
      at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:4213:16)
      at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4277:31)
      at reportUncaughtErrorInDEV (node_modules/react-dom/cjs/react-dom.development.js:22877:5)
      at captureCommitPhaseError (node_modules/react-dom/cjs/react-dom.development.js:27165:5)
      at safelyCallDestroy (node_modules/react-dom/cjs/react-dom.development.js:22973:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24142:23)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
...
      at commitMutationEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24471:9)
      at commitMutationEffects (node_modules/react-dom/cjs/react-dom.development.js:24282:3)
      at commitRootImpl (node_modules/react-dom/cjs/react-dom.development.js:26849:5)
      at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:26721:5)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:26156:3)
      at flushSyncCallbacks (node_modules/react-dom/cjs/react-dom.development.js:12042:22)
      at flushSync (node_modules/react-dom/cjs/react-dom.development.js:26240:7)
      at ReactDOMRoot.Object.<anonymous>.ReactDOMHydrationRoot.unmount.ReactDOMRoot.unmount [as unmount] (node_modules/react-dom/cjs/react-dom.development.js:29375:5)
      at Object.unmount (node_modules/@testing-library/react/dist/pure.js:155:12)
      at node_modules/@testing-library/react/dist/pure.js:286:12
      at node_modules/@testing-library/react/dist/act-compat.js:48:24
      at act (node_modules/react/cjs/react.development.js:2512:16)
      at node_modules/@testing-library/react/dist/act-compat.js:47:25
      at node_modules/@testing-library/react/dist/pure.js:285:28
          at Array.forEach (<anonymous>)
      at cleanup (node_modules/@testing-library/react/dist/pure.js:281:22)
      at Object.<anonymous> (node_modules/@testing-library/react/dist/index.js:28:25)

  console.error
    The above error occurred in the <ForwardRef(SelectImpl)> component:
    
        at SelectImpl (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@ark-ui/react/dist/components/select/select-root.cjs:48:28)
        at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@emotion/react/dist/emotion-element-25f9958c.browser.cjs.js:56:23
        at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@chakra-ui/react/dist/cjs/styled-system/create-slot-recipe-context.cjs:73:28
        at div
        at /home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@emotion/react/dist/emotion-element-25f9958c.browser.cjs.js:56:23
        at Stack2 (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@chakra-ui/react/dist/cjs/components/stack/stack.cjs:19:7)
        at VStack2
        at div
        at Page (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/app/page.tsx:24:49)
        at X (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/next-themes/dist/index.js:1:1591)
        at F (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/next-themes/dist/index.js:1:1472)
        at ColorModeProvider
        at ChakraProvider (/home/boyland/Documents/Courses/sp25-cs552/project/test-select/node_modules/@chakra-ui/react/dist/cjs/styled-system/provider.cjs:15:18)
        at Provider
    
    Consider adding an error boundary to your tree to customize error handling behavior.
    Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.

      at logCapturedError (node_modules/react-dom/cjs/react-dom.development.js:18704:23)
      at update.callback (node_modules/react-dom/cjs/react-dom.development.js:18737:5)
      at callCallback (node_modules/react-dom/cjs/react-dom.development.js:15036:12)
      at commitUpdateQueue (node_modules/react-dom/cjs/react-dom.development.js:15057:9)
      at commitLayoutEffectOnFiber (node_modules/react-dom/cjs/react-dom.development.js:23430:13)
      at commitLayoutMountEffects_complete (node_modules/react-dom/cjs/react-dom.development.js:24727:9)
      at commitLayoutEffects_begin (node_modules/react-dom/cjs/react-dom.development.js:24713:7)
      at commitLayoutEffects (node_modules/react-dom/cjs/react-dom.development.js:24651:3)
      at commitRootImpl (node_modules/react-dom/cjs/react-dom.development.js:26862:5)
      at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:26721:5)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:26156:3)
      at flushSyncCallbacks (node_modules/react-dom/cjs/react-dom.development.js:12042:22)
      at flushSync (node_modules/react-dom/cjs/react-dom.development.js:26240:7)
      at ReactDOMRoot.Object.<anonymous>.ReactDOMHydrationRoot.unmount.ReactDOMRoot.unmount [as unmount] (node_modules/react-dom/cjs/react-dom.development.js:29375:5)
      at Object.unmount (node_modules/@testing-library/react/dist/pure.js:155:12)
      at node_modules/@testing-library/react/dist/pure.js:286:12
      at node_modules/@testing-library/react/dist/act-compat.js:48:24
      at act (node_modules/react/cjs/react.development.js:2512:16)
      at node_modules/@testing-library/react/dist/act-compat.js:47:25
      at node_modules/@testing-library/react/dist/pure.js:285:28
          at Array.forEach (<anonymous>)
      at cleanup (node_modules/@testing-library/react/dist/pure.js:281:22)
      at Object.<anonymous> (node_modules/@testing-library/react/dist/index.js:28:25)

 FAIL  app/page.test.tsx
  Page has required parts
    ✓ renders size selector label (174 ms)
    ✕ select an option #2 (218 ms)

  ● Page has required parts › select an option #2

    ReferenceError: ResizeObserver is not defined

      at Object.autoUpdate (node_modules/@floating-ui/dom/dist/floating-ui.dom.umd.js:773:7)
      at getPlacementImpl (node_modules/@zag-js/popper/dist/index.js:259:52)
      at node_modules/@zag-js/popper/dist/index.js:274:21
      at invokeTheCallbackFunction (node_modules/jsdom/lib/jsdom/living/generated/Function.js:19:26)
      at runAnimationFrameCallbacks (node_modules/jsdom/lib/jsdom/browser/Window.js:603:13)
      at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/browser/Window.js:581:11)

  ● Page has required parts › select an option #2

    TypeError: dom.getContentEl(...)?.scrollTo is not a function

      at scrollContentToTop (node_modules/@zag-js/select/dist/index.js:978:37)
      at Machine.executeActions (node_modules/@zag-js/core/dist/index.js:469:13)
      at Machine.performExitEffects (node_modules/@zag-js/core/dist/index.js:550:12)
      at Machine.stop (node_modules/@zag-js/core/dist/index.js:261:12)
      at node_modules/@zag-js/react/dist/index.js:170:15
      at safelyCallDestroy (node_modules/react-dom/cjs/react-dom.development.js:22971:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24142:23)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24209:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24209:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24057:11)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24057:11)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24209:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24209:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at recursivelyTraverseDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24028:5)
      at commitDeletionEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24157:9)
      at commitDeletionEffects (node_modules/react-dom/cjs/react-dom.development.js:24015:5)
      at recursivelyTraverseMutationEffects (node_modules/react-dom/cjs/react-dom.development.js:24298:9)
      at commitMutationEffectsOnFiber (node_modules/react-dom/cjs/react-dom.development.js:24471:9)
      at commitMutationEffects (node_modules/react-dom/cjs/react-dom.development.js:24282:3)
      at commitRootImpl (node_modules/react-dom/cjs/react-dom.development.js:26849:5)
      at commitRoot (node_modules/react-dom/cjs/react-dom.development.js:26721:5)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:26156:3)
      at flushSyncCallbacks (node_modules/react-dom/cjs/react-dom.development.js:12042:22)
      at flushSync (node_modules/react-dom/cjs/react-dom.development.js:26240:7)
      at ReactDOMRoot.Object.<anonymous>.ReactDOMHydrationRoot.unmount.ReactDOMRoot.unmount [as unmount] (node_modules/react-dom/cjs/react-dom.development.js:29375:5)
      at Object.unmount (node_modules/@testing-library/react/dist/pure.js:155:12)
      at node_modules/@testing-library/react/dist/pure.js:286:12
      at node_modules/@testing-library/react/dist/act-compat.js:48:24
      at act (node_modules/react/cjs/react.development.js:2512:16)
      at node_modules/@testing-library/react/dist/act-compat.js:47:25
      at node_modules/@testing-library/react/dist/pure.js:285:28
          at Array.forEach (<anonymous>)
      at cleanup (node_modules/@testing-library/react/dist/pure.js:281:22)
      at Object.<anonymous> (node_modules/@testing-library/react/dist/index.js:28:25)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        1.953 s, estimated 2 s
Ran all test suites.

Solution

  • Click is the way to go, after polyfilling the missing properties. First get the ResizeObserver polyfill:

    npm i -D resize-observer-polyfill
    

    Then update jest.setup.js with this additional code

    import ResizeObserver from 'resize-observer-polyfill';
    
    if (typeof global.ResizeObserver === "undefined") {
      global.ResizeObserver = ResizeObserver;
    }
    
    if (typeof Element.prototype.scrollTo === "undefined") {
        // mock scrollTo for tests that may call it
        Element.prototype.scrollTo = jest.fn();
    }
    

    Now the following test works:

    test('select an option #2', async () => {
            const user = userEvent.setup();
            chakraRender(<Page />);
            const sizeSelector = screen.getByRole('combobox', {name: /Choose a size/i });
            await user.click(sizeSelector);
            const option = screen.getByRole('option', {name: '75'});
            await user.click(option); // This simulates selecting the option from the dropdown
            await waitFor(() => expect(sizeSelector).toHaveTextContent('75'));
    });