Nikko
Nikko

Reputation: 301

React Testing Library user-event throws error `TypeError: root.elementFromPoint is not a function`

I am trying to write a test which writes a / in an editor and observes a menu appearing. For this I try to use the userEvent.type() method that simulates real keyboard typing events. However, I get the error Error: Uncaught [TypeError: root.elementFromPoint is not a function](see full error on bottom)

I have tried a few things, and I've included the (not-working) test below:

The RichTextRenderer is a react component that uses TipTap (based on Prosemirror) to create blocks of editable text. The thing is, I'd understand type() not to work maybe because it's a content-editable div. However, click() also doesn't work which totally doesn't make sense. And when I google elementFromPoint it's a function, so the error is also weird. How can I get userEvent.type() to work and actually change the content of the paragraph with role "editor"?

I have written the following test:

test("Typing slash opens the slash menu", async () => {
  render(
    <DndProvider backend={HTML5Backend}>
      <RichTextRenderer/>
    </DndProvider>
  );
  const block = screen.getByRole("editor");
  screen.debug();
  expect(block).toBeInTheDocument();
  userEvent.type(block, "/");
}, 10000);

and screen.debug() prints the following tree:

    <body>
      <div>
        <div>
          <div>
            <div
              aria-expanded="false"
              class="ProseMirror editor"
              contenteditable="true"
              tabindex="0"
            >
              <p
                class="is-empty is-editor-empty"
                data-placeholder=""
                role="editor"
              >
                <br />
              </p>
            </div>
          </div>
        </div>
      </div>
    </body>

the full error given is:

 console.error
    Error: Uncaught [TypeError: root.elementFromPoint is not a function]
        at reportException (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
        at innerInvokeEventListeners (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
        at invokeEventListeners (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
        at HTMLParagraphElementImpl._dispatch (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
        at HTMLParagraphElementImpl.dispatchEvent (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
        at HTMLParagraphElement.dispatchEvent (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
        at /home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/dom/dist/events.js:25:20
        at /home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/react/dist/pure.js:66:16
        at batchedUpdates$1 (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/react-dom/cjs/react-dom.development.js:22380:12)
        at act (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14) TypeError: root.elementFromPoint is not a function
        at posAtCoords (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/prosemirror-view/src/domcoords.js:245:18)
        at EditorView.posAtCoords$1 [as posAtCoords] (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/prosemirror-view/src/index.js:275:12)
        at Object.<anonymous>.handlers.mousedown (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/prosemirror-view/src/input.js:266:18)
        at HTMLDivElement.view.dom.addEventListener.view.eventHandlers.<computed> (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/prosemirror-view/src/input.js:46:9)
        at HTMLDivElement.callTheUserObjectsOperation (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
        at innerInvokeEventListeners (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
        at invokeEventListeners (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
        at HTMLParagraphElementImpl._dispatch (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
        at HTMLParagraphElementImpl.dispatchEvent (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
        at HTMLParagraphElement.dispatchEvent (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
        at /home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/dom/dist/events.js:25:20
        at /home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/react/dist/pure.js:66:16
        at batchedUpdates$1 (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/react-dom/cjs/react-dom.development.js:22380:12)
        at act (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
        at Object.eventWrapper (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/react/dist/pure.js:65:28)
        at fireEvent (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/dom/dist/events.js:16:35)
        at Function.fireEvent.<computed> [as mouseDown] (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/dom/dist/events.js:125:36)
        at clickElement (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/user-event/dist/click.js:72:52)
        at click (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/user-event/dist/click.js:136:7)
        at typeImpl (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/user-event/dist/type.js:172:36)
        at Object.type (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/@testing-library/user-event/dist/type.js:155:14)
        at Object.<anonymous> (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/src/documentRenderers/richtext/test/slashMenu.test.tsx:39:13)
        at _callCircusTest (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/run.js:212:5)
        at _runTest (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/run.js:149:3)
        at _runTestsForDescribeBlock (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/run.js:63:9)
        at run (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/run.js:25:3)
        at runAndTransformResultsToJestFormat (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:176:21)
        at jestAdapter (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:109:19)
        at runTestInternal (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-runner/build/runTest.js:380:16)
        at runTest (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-runner/build/runTest.js:472:34)
        at Object.worker (/home/nikko/Folders/Uni/SoftwareProject/typecell-next/node_modules/jest-runner/build/testWorker.js:133:12)

      at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
      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:341:9)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
      at HTMLParagraphElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
      at HTMLParagraphElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)

Upvotes: 2

Views: 4787

Answers (2)

Mujjasim Khan
Mujjasim Khan

Reputation: 1

We need to mock document.elementFromPoint. add document.elementFromPoint = () => {} before describe().

Upvotes: 0

olpa
olpa

Reputation: 1227

The testing library is most likely based on jsdom, which doesn't implement layouting. At the same time, Prosemirror (and therefore TipTap) uses the layout information.

For my tests, it was enough to stub layouting functions.

function getBoundingClientRect(): DOMRect {
  const rec = {
    x: 0,
    y: 0,
    bottom: 0,
    height: 0,
    left: 0,
    right: 0,
    top: 0,
    width: 0,
  };
  return { ...rec, toJSON: () => rec };
}

class FakeDOMRectList extends Array<DOMRect> implements DOMRectList {
  item(index: number): DOMRect | null {
    return this[index];
  }
}

document.elementFromPoint = (): null => null;
HTMLElement.prototype.getBoundingClientRect = getBoundingClientRect;
HTMLElement.prototype.getClientRects = (): DOMRectList =>
  new FakeDOMRectList();
Range.prototype.getBoundingClientRect = getBoundingClientRect;
Range.prototype.getClientRects = (): DOMRectList =>
  new FakeDOMRectList();

Upvotes: 3

Related Questions