Has anyone successfully used react-testing-library to test change events on a draftJS Editor component?
Asked Answered
E

2

9

​The fireEvent.change() just doesn't work.

It says there are no setters on the element.

I tried using aria selectors instead

const DraftEditor = getByRole('textbox')
DraftEditor.value ='something';
fireEvent.change(DraftEditor);

I tried same again using query selector

const DraftEditor = container.querySelector('.public-DraftEditor-content'));

Tried keyboard events instead.

Nothing.

Has anyone managed to text a rich text input with draftjs and react testing library?

Engel answered 12/4, 2019 at 6:17 Comment(4)
Any new on this?Cispadane
Nope. I gave up and ended up using cypress to do the test instead.Engel
yeah so do I :)Cispadane
A longer discussion on ways around this has been fleshed out on spectrum hereEngel
B
11

I managed to do it by getting inspiration from some issue description for draft-js and adapting that to our case at hand

import { createEvent } from "@testing-library/dom"
import { render, fireEvent } from "@testing-library/react"

function createPasteEvent(html) {
  const text = html.replace('<[^>]*>', '');
  return {
    clipboardData: {
      types: ['text/plain', 'text/html'],
      getData: (type) => (type === 'text/plain' ? text : html),
    },
  };
}

renderedComponent = render(<App />)
const editorNode = renderedComponent.querySelector(".public-DraftEditor-content")
const eventProperties = createPasteEvent(textToPaste)
const pasteEvent = createEvent.paste(editorNode, eventProperties)
pasteEvent.clipboardData = eventProperties.clipboardData
fireEvent(editorNode, pasteEvent)

Some additional notes:

  • renderedComponent in my case is the parent element in which the Editor component is rendered.
  • apparently, 'ClipboardEvent' is not implemented in JSDOM (see list of supported events), therefore, the call to createEvent.paste creates a generic Event, and not a ClipboardEvent. As a workaround, I copy the necessary clipboardData properties again to the generated generic event so that they will be taken into account by the function editOnPaste of the Draft-js editor, which itself will be triggered because of the fired event.
Bierce answered 18/10, 2019 at 13:49 Comment(2)
this worked well, but it breaks on latest testing-library/dom version as pastEvent is readonlyOquendo
@SibeliusSeraphini is right, but it seems the offending line (pasteEvent.clipboardData = ...) is not necessary?Offset
D
2

I managed to get it working mocking the editor and intercepting the onChange method so you can still execute all the lib functions:

const draftjs = require('draft-js');

draftjs.Editor = jest.fn(props => {
  const modifiedOnchange = e => {
    const text = e.target.value;
    const content = ContentState.createFromText(text);
    props.onChange(EditorState.createWithContent(content));
  };
  return <input className="editor" onChange={e => modifiedOnchange(e)} />;
});
Defrock answered 20/2, 2020 at 13:53 Comment(2)
I am really looking for a solution like this, but I couldn't find a way to mock it myself. Tried your answer but is says ContentState is not definedJarib
You have to import Content state class from draft jsDefrock

© 2022 - 2024 — McMap. All rights reserved.