How to test svelte input reactivity?

1.8k views Asked by At

I wrote a svelte component App in which you can write a sentence in an input and the sentence will be render in a h1.

App.svelte

<script>
  let sentence = "Hello world";
</script>

<main>
  <h1>{sentence}</h1>
  <input
    value={sentence}
    type="text"
    on:input={(value) => {
      sentence = value.target.value
    }}
  />

</main>

But when I tried to test this behaviour using @testing-library/svelte, the input is not reactive and the text in h1 is still "Hello world" (but the value in the input has changed according to the first expect).

App.test.js

import { render, fireEvent } from "@testing-library/svelte";
import App from "./App.svelte";

it("should write in input", async () => {
  const { container } = render(App);
  const input = container.querySelector("input[type=text]");

  await fireEvent.change(input, { target: { value: "test" } });

  expect(input.value).toBe("test"); // ✅
  expect(container.querySelector("h1").textContent).toBe("test"); // ❌
});

Jest error message:

Expected: "test"
Received: "Hello world"

   8 |   await fireEvent.change(input, { target: { value: "test" } });
  10 |   expect(input.value).toBe("test");
> 11 |   expect(container.querySelector("h1").textContent).toBe("test");
  12 | });

You can check this behaviour using the codesandbox.

Has someone an idea why this test is failing?

2

There are 2 answers

0
Carlos Roso On BEST ANSWER

TL;DR:

Use fireEvent.input(...) as you suggest in the comments.

Original thought:

I wonder if that's related to the fact that it's triggering a change event when Svelte is subscribed to the input event. Try changing it to on:change and you'll see the test passing. Now, the ideal situation would be to have fireEvent triggering an 'input' event.

0
Deotyma On

And if you import at the beginning of the file:

import { screen } from '@testing-library/dom'

and at the end you put this:

 expect(
      await screen.findByText('test'),
    ).toBeVisible()