Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Testing with React Testing Library #2833

Open
dwjohnston opened this issue Feb 22, 2021 · 4 comments
Open

Testing with React Testing Library #2833

dwjohnston opened this issue Feb 22, 2021 · 4 comments

Comments

@dwjohnston
Copy link

dwjohnston commented Feb 22, 2021

Do you want to request a feature or report a bug?

Feature / Help Required

What is the current behavior?

My use is in actually using Draftail, which uses DraftJS under the hood. (I'm actually working on Draftail fork, as Draftail is not passing all of the aria properties to the DraftJS, my work is linked below).

I want to simulate entering some text, and then make assertions about what effect that has in my application.

What I have tried for example, is something like this:

        const saveHandler = jest.fn();

        render(<DraftailEditor
            ariaDescribedBy='foo'
            ariaLabel="aria label"
            inlineStyles={[]}
            spellCheck={false}
            rawContentState={{
                entityMap: {},
                blocks: [
                  {
                    key: "aaa",
                    text:
                      "abc",
                  },
                ],
              }}
            blockTypes={[]}
            onSave={saveHandler}
            placeholder="placeholder"
            className="classname"
        />);


        const textbox = screen.getByRole("textbox", {
            name: "aria label"
        });


        // Check initial value exists 
        getByText(textbox, "abc");

        // Everything is fine till here. 

        userEvent.type('textbox', '123'); 


        //fails 
        getByText(screen.getByRole("textbox", {
            name: "aria label"
        }), "abc123");

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. You can use this jsfiddle to get started: https://jsfiddle.net/gmertk/e61z7nfa/.

Repro of this on this branch and file here: https://github.com/dwjohnston/draftail/blob/draftjs-issue/tests/rtl.test.js

What is the expected behavior?

The draftjs editor responds userEvent methods, ie. the content of the editor is updated.

Which versions of Draft.js, and which browser / OS are affected by this issue? Did this work in previous versions of Draft.js?

draftjs 10.5
jest-dom

Other notes:

I have investigated other techniques such as:

#325 (comment)

This one looks platform/test framework agnostic, but that
var textEvent = document.createEvent('TextEvent'); gives the error:

NotSupportedError: The provided event type ("TextEvent") is invalid

I've updated that to:


    function addTextToDraftJs(className) {
        const components = document.getElementsByClassName(className);
        if(components && components.length) {
          const textarea = components[0].getElementsByClassName('public-DraftEditor-content')[0];
          const keyboardEvent = new KeyboardEvent("keyDown", {
            key: "a"
          });           
          textarea.dispatchEvent(keyboardEvent);
        }  
      }


      addTextToDraftJs('Draftail-Editor');

      await new Promise((res) => setTimeout(()=> res(null), 1000)); // Just incase it's an async issue 

But the content does not appear to update.

This comment seems to suggest that a keydown/keypress even would not work, and that a textInput event is what would be required. But I'm not sure what that is or how I would emit it.

A lot of the proposed solutions such as:

#325 (comment)
#325 (comment)
#325 (comment)

Seem to rely on using using Enzyme and using the react class instance to simulate an event.

It seems like it is not possible to access a components class instance from RTL.

#347

This one looks quite out of date, and my understand is to the the TestUtils methods, I would need access to the component's class instance.

@dwjohnston
Copy link
Author

OK, so after doing a bit of investigation it looks like JSDom doesn't support the "TextEvent" type, which that comment suggests you need.

Any suggestions for how we can extend JSDom to allow it?

@dwjohnston
Copy link
Author

dwjohnston commented Feb 22, 2021

Ok, following this comment, it looks like we have a solution.

  it.only ("You can update the state of it (no hack)", async () => {

    const saveHandler = jest.fn();


    render(
      <DraftailEditor
        ariaDescribedBy="foo"
        ariaLabel="aria label"
        inlineStyles={[]}
        spellCheck={false}
        rawContentState={{
          entityMap: {},
          blocks: [
            {
              key: "aaa",
              text: "abc",
            },
          ],
        }}
        blockTypes={[]}
        onSave={saveHandler}
        placeholder="placeholder"
        className="classname"
      />,


      
    );

    const textarea = screen.getByRole("textbox", {
      name: "aria label",
    });

    const event = createEvent.paste(textarea, {
      clipboardData:{
        types: ['text/plain'],
        getData: () => "hello" // The linked comment had stuff around pasting html in, I can't see that it's needed for this test. 
      }
    }); 


    fireEvent(textarea, event);
    
     getByText(screen.getByRole("textbox", {
            name: "aria label"
        }), "abchello");
  }); 

Basically RTL's createEvent does not have a way to create a TextEvent Event, and JSDom doesn't have a TextEvent, but RTL does have a paste event, which it seems that draft-js listens to.

So this works.

This solution doesn't work for every testing scenario - for example I don't think it'll work for testing custom key bindings, or things like hitting backspace/delete etc, but works fine for just entering some text.

@dwjohnston
Copy link
Author

We can close this issue - or do we want to update the documentation to reflect 'How to use with RTL'?

@fabb
Copy link

fabb commented Apr 19, 2021

pasting could behave differently than typing depending on implementation, so while this solution is a helpful stop-gap, it's not an ideal solution imho.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants