Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to test a non-bound change in the DOM #119

Closed
unknownterritory opened this issue Jan 29, 2021 · 6 comments
Closed

Unable to test a non-bound change in the DOM #119

unknownterritory opened this issue Jan 29, 2021 · 6 comments

Comments

@unknownterritory
Copy link

I am new to testing-library, so I hope I'm not missing anything obvious.

I have a helper class whose methods make changes in a component's DOM, some upon interaction by the user. I am unable to test those changes with fireEvent or userEvent. It always fails.

I simplified my use case to a very simple example:

  • My svelte component has only a button that modifies the content of a paragraph. The paragraph's content is not bound to a variable intentionally.
  • And then I have a test for it. The test expect(info).toHaveTextContent("Modified by click") fails but, curiously enough, a console.log(paragraph.innerText) shows the change.
  • I also have a codesandbox replicating this example.

Code for the component:

<script>
  // The text content of the paragraph is purposely not bound
  // with any svelte variable. The purpose of this exercise
  // is to reduce to the simplest form my use-case which is
  // to test changes done in html elements of a svelte component
  // by external helper class methods, which do not allow for
  // bindings to exist.
  const modify = () => {
    const par = document.querySelector(".info");
    par.innerText = "Modified by click";
  };
</script>

<div>
  <p class="info" data-testid="info">Click to modify</p>
  <button on:click={modify} label="button">Modify</button>
</div>

The code for the test.

import { render, screen, waitFor } from "@testing-library/svelte";
import "@testing-library/jest-dom/extend-expect";
import userEvent from "@testing-library/user-event";
import Component from "./Component.svelte";

it("should modify the text after clicking the button", async () => {
  render(Component);
  const button = screen.getByRole("button");
  userEvent.click(button);
  const info = screen.getByTestId("info");
  // console.log actually outputs the modified content?
  console.log(info.innerText);
  // The test fails independently of using waitFor or not.
  await waitFor(() => {
    expect(info).toHaveTextContent("Modified by click");
  });
});

Is this a bug of the library or should I be approaching this test differently?

P.S.: I asked on Discord, both in the testing-library and the svelte communities. I've also researched the documentation and previous issues. While I'm not entirely sure this is a bug, I would very much appreciate an indication of where to seek a solution if the fault resides in my approach.

@airedwin
Copy link

I have similar problem when testing button clicks that will change the DOM. Sometimes it works, sometimes it doesn't.

@PClmnt
Copy link

PClmnt commented Jan 26, 2022

I'm nearly sure i'm running into the same issue.

It doesn't seem to re-render the dom after a click event.

@blindfish3
Copy link

blindfish3 commented Sep 28, 2023

I'm experiencing the same symptoms when testing a modal component. An initial test interaction triggers a change in the component (the menu content goes from hidden to rendered); but a subsequent interaction in the same test - that should close the menu - fails to update the 'rendered' output (e.g. as seen in debug()) and the test fails. Inspecting the property that controls visibility shows it has updated 😕
I tried wrapping my expect() in a waitFor() thinking it might simply be a timing issue; but the update render never happens...

edit: in my case it appears that the problem is the use of a transition in the tested component. See #206

yanick added a commit that referenced this issue Jan 23, 2024
Takes care of the lack of reactivity seen in #119
@yanick
Copy link
Collaborator

yanick commented Jan 23, 2024

It seems that using happy-dom instead of jsdom fixes the problem!

yanick added a commit that referenced this issue Jan 23, 2024
Takes care of the lack of reactivity seen in #119
@mcous
Copy link
Collaborator

mcous commented Jan 24, 2024

The cause of this, specifically, is that jsdom does not support innerText. There are two available solutions to work around this, neither of which involve svelte-testing-library:

  1. Switch test runner to Vitest + happy-dom
    • happy-dom supports innerText
    • In my experience, happy-dom is not a simple drop-in replacement for jsdom, depending on your test suite
    • Vitest is great, but also not necessarily a drop-in replacement for Jest
  2. Switch implementation to use .textContent or .innerHTML instead of .innerText
    • Note: both of these have important differences from innerText that should be considered before changing your implementation

@yanick I think this ticket should be considered outside the scope of svelte-testing-library closed. I don't think switching our tests to happy-dom is the right move at this time (see my comment in #286 for reasoning)

@yanick
Copy link
Collaborator

yanick commented Jan 24, 2024

@yanick I think this ticket should be considered outside the scope of svelte-testing-library closed. I don't think switching our tests to happy-dom is the right move at this time (see my comment in #286 for reasoning)

Agreed. And having the tests run both under jsdom and happy-dom strikes me as better than flopping around. But that's a talk for #286 :-)

@yanick yanick closed this as completed Jan 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants