Skip to content

fireEvent does not seem to work properly with non-default container #623

@msandrini

Description

@msandrini

In a test file comprised of two tests, I first tried matching a React rendered container (obtained from render) against a snapshot, which issued a success as expected. In the second test, I used fireEvent to issue a click and the DOM apparently didn't update as it should. Funny thing is, if I invert the test order both of them works. Even funnier: when I put up a codesandbox to recreate the issue (URL below), it fails on the first time it is seen and then it succeeds if I change the order of tests and then change it back.

I put a log call to see whether the events are being fired on this possibly buggy case, and it turns out they aren't.

A relevant detail is that I'm not rendering the element on top of the standard element provided, but rather (as it is a TD) I'm rendering on top of a table/tr.

  • @testing-library/react version: 10.0.1
  • react version: 16.13.0
  • node version: 12.11.1
  • npm (or yarn) version: 6.11.3

Relevant code or config:

Component:

import React, { useState } from "react";

const Component = ({ initialValue }) => {
  const [text, setText] = useState(initialValue || "");

  const handleTextChange = event => {
    setText(event.target.value);
  };

  return (
    <td className="x">
      <textarea value={text || ""} onChange={handleTextChange} />
    </td>
  );
};

export default Component;

Test:

import React from "react";
import { render, fireEvent } from "@testing-library/react";

import App from "./App";

const table = document.createElement("table");
const tr = document.createElement("tr");
const renderOptions = {
  container: document.body.appendChild(table.appendChild(tr))
};

describe("<App />", () => {
  it("with defaults (read-only user)", () => {
    const { container } = render(<App initialValue="blah" />, renderOptions);
    expect(container).toBeTruthy(); // I was comparing to snaphots, but it's not needed
  });
  it("should change text on textarea", () => {
    const utils = render(<App initialValue="initial value" />, renderOptions);
    const textarea = utils.getByRole("textbox");
    fireEvent.change(textarea, { target: { value: "modified text" } });

    expect(textarea.innerHTML).toEqual("modified text");
  });
});

What you did:

Set up the tests above against the component, also above, and it fails when the tests have the order above. If I invert the order of tests or swap the TD to a DIV and don't render against the table/tr, they work.

What happened:

expect(received).toEqual(expected)

Expected value to equal:
  "modified text"
Received:
  "initial value"

  19 |     const textarea = utils.getByRole("textbox");
  20 |     fireEvent.change(textarea, { target: { value: "abc" } });
> 22 |     expect(textarea.innerHTML).toEqual("abc");
  23 |   });
  24 | });

Reproduction:

https://codesandbox.io/s/testing-lib-react-445bv

Problem description:

Unless I'm missing something, this is not only an inconsistency but a bug, as the test above should succeed at all times, no matter the order of tests on the test file.

Suggested solution:

I don't know what would be the solution but I would guess it has something to do with the fact that I am issuing render with a different container option, in this case a table row (table/tr), rather than going with the default body/div.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions