RocketCommunicationsInc / astro

Astro UXDS is a collection of guidelines, patterns and components for designing space-based user interface applications.
https://astrouxds.com
Other
108 stars 25 forks source link

Testing RuxInput in React with react-testing-library #1114

Closed micahjones13 closed 1 year ago

micahjones13 commented 1 year ago

image I am trying to replicate this test and am having a few problems. For the RuxInput, the setInput is not a prop to RuxInput, I changed this to onRuxinput and that resolved the issue with syntax. When I run this test, the userEvent.type(shadowInput, 'User input!') does not seem to fire the onRuxinput which makes it hard to test functionality that would go this RuxInput. Any tips or advice would be appreciated.

Originally posted by @jarod-oa in https://github.com/RocketCommunicationsInc/astro/discussions/1113#discussioncomment-5608329

mrclean-oa commented 1 year ago

Possibly related to https://github.com/RocketCommunicationsInc/astro/issues/115?

micahjones13 commented 1 year ago

For the RuxInput, the setInput is not a prop to RuxInput, I changed this to onRuxinput and that resolved the issue with syntax

Yup, looks like I screwed up the code in the docs, thanks for catching that. I'll change it ASAP. It should look like:

    <div>
      <RuxInput
        label="Rux Input"
        type="text"
        data-testid="rux-input-test"
        value={input}
        onRuxinput={(e: CustomEvent<HTMLRuxInputElement>) => {
          const target = e.target as HTMLInputElement;
          setInput(target.value);
        }}
      />
    </div>

When I run this test, the userEvent.type(shadowInput, 'User input!') does not seem to fire

Are you getting any sort of error when you run the test, or is it just failing with no helpful output?

In case it's helpful, I created a fresh repo to test this all out in. It's working, but the test command had to be updated to "react-scripts test --transformIgnorePatterns=\"node_modules/(?!@astrouxds/react)/\" --env=jsdom" in order to run without error.

I apologize again for the incorrect documentation. Please let me know if the above helps, or if there is anything else I can do!

jarod-oa commented 1 year ago

Hey Micah, this still doesn't fix my issue.

form

<div>
      <RuxInput
        label="Rux Input"
        data-testid="rux-input-test"
        value={input}
        onRuxinput={(e: CustomEvent<HTMLRuxInputElement>) => {
          const target = e.target as HTMLInputElement;
          setInput(target.value);
          console.log("hello")
        }}
      />
    </div>

test

    render(
      <RuxInputTest />
    );
    const ruxInput = await screen.getByTestId('rux-input-test') as HTMLInputElement;
    await act(async () => {
      await userEvent.type(ruxInput, 'every character fires console.log')
    });
    expect(value.testValue).toBe(230);
  });

package.json

"test": "jest --env=jsdom",

jest.config.js

transformIgnorePatterns: ["node_modules/(?!@astrouxds/react)"],

babel.config.json

{
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/transform-runtime"
  ],
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript",
    "@babel/preset-react"
  ]
}

Sorry this is a lot, but using the jest with the UserEvent.type() should make a console.log fire for every character but it is never happening. When I replace the with a native tag it works as expected. Does the use of jest change this?

micahjones13 commented 1 year ago

Alright, I've mimicked that test as much as I could, and I'm seeing the console logs fire when I run the tests. I did have to change it a bit because I'm just missing some context, but this is what I've got:

//imports 
import { render, fireEvent, act, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { within } from "testing-library__dom";
import RuxInputTest from "./form";

test("Test", async () => {
    render(<RuxInputTest />);
    const ruxInput = screen.getByTestId("rux-input-test") as HTMLInputElement;
    const shadowInput: HTMLInputElement = await within(
      ruxInput
    ).findByLabelText("Rux Input");
    await act(async () => {
      await userEvent.type(shadowInput, "every character fires console.log");
    });
    expect(shadowInput.value).toBe("every character fires console.log");
  });

I think the important part here is probably using the within function from testing-library__dom. This allows the test to pierce the shadow dom of RuxInput, which then allows for the userEvent.type to work.

jarod-oa commented 1 year ago

Hey Micah,

This got it to work, thanks for the help. I thought I had tried the testing-library__dom but must not have done it correctly. Sorry about the code being a little bit off, I had changed it for a function and didn't change it back to how it was to match your test.

micahjones13 commented 1 year ago

No worries! I'm glad it's working out. RTL and shadow dom are not friends, so hopefully it goes smoother from here on out. If not, please feel free to reach out to us! You can open a new issue/discussion, or if you'd rather you can email me directly at micah.jones@rocketcom.com.