Reputation: 301
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
Reputation: 1
We need to mock document.elementFromPoint. add document.elementFromPoint = () => {} before describe().
Upvotes: 0
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