You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been using svelte-testing-library for a few months now on a new Svelte project, and I'm enjoying it! Thanks for all your hard work.
I ran into an issue today that I wanted to highlight, because it seems to me like it should be a relatively normal thing to want to test with this library: changes to prop values trigger correct behaviors in already rendered components.
Overview
As a test author, I'd like to test that my component reacts properly to props changes by, for example, updating existing DOM elements. However, because rerender unmounts the component, DOM elements queried before the rerender are removed from the document and component state is lost.
It seems like #210 may address this issue, but it hasn't been reviewed. I think any change to rerender in this regard would also be a breaking change to the API.
Example
I am writing a component that puts a message in a role=status area. Per WAI, the procedure to test this is:
Check that the container destined to hold the status message has a role attribute with a value of status before the status message occurs.
Check that when the status message is triggered, it is inside the container.
Check that elements or attributes that provide information equivalent to the visual experience for the status message (such as a shopping cart image with proper ALT text) also reside in the container.
The test that I wrote naively using rerender looks like this:
it('should display an unsaved changes message if unsaved',()=>{const{ rerender }=render(UpdateStatus,{isUnsaved: false})conststatus=screen.getByRole('status',{name: 'update status'})expect(status).toHaveTextContent('')rerender({isUnsaved: true})expect(status).toHaveTextContent(/unsaved changes/iu)});
Expected behavior
The test passes
Actual behavior
The test fails, because after the rerender, the status DOM element still has no text content, because it was unmounted and a new one was created.
Workarounds / alternatives considered
I've tried out the following alternatives, none of which feel super ideal. I'd be curious if you had any others!
Re-query elements
The test will pass if I re-query the DOM elements. I dislike this approach because it does not satisfy the recommended test procedure above.
it('should display an unsaved changes message if unsaved',()=>{const{ rerender }=render(UpdateStatus,{isUnsaved: false})letstatus=screen.getByRole('status',{name: 'update status'})expect(status).toHaveTextContent('')rerender({isUnsaved: true})status=screen.getByRole('status',{name: 'update status'})expect(status).toHaveTextContent(/unsaved changes/iu)});
Interact with Svelte component directly
I can update props on the Svelte component directly. I dislike this approach because:
The act is awkward, but necessary to ensure the component is re-rendered
The docs tell me not to use component:
Generally, this should only be used when testing exported functions, or when you're testing developer facing API's. Outside of said cases avoid using the component directly to build tests
it('should display an unsaved changes message if unsaved',async()=>{const{ component }=render(UpdateStatus,{isUnsaved: false})conststatus=screen.getByRole('status',{name: 'update status'})expect(status).toHaveTextContent('')awaitact(()=>{component.$set({isUnsaved: true})})expect(status).toHaveTextContent(/unsaved changes/iu)});
Create a wrapper component for testing
I can create a wrapper testing component that updates the prop on a button click (or similar). I dislike this approach because it bloats my test suite and adds a layer of misdirection between my test and the component that I'm actually testing.
I've been using svelte-testing-library for a few months now on a new Svelte project, and I'm enjoying it! Thanks for all your hard work.
I ran into an issue today that I wanted to highlight, because it seems to me like it should be a relatively normal thing to want to test with this library: changes to prop values trigger correct behaviors in already rendered components.
Overview
As a test author, I'd like to test that my component reacts properly to props changes by, for example, updating existing DOM elements. However, because
rerender
unmounts the component, DOM elements queried before thererender
are removed from the document and component state is lost.It seems like #210 may address this issue, but it hasn't been reviewed. I think any change to
rerender
in this regard would also be a breaking change to the API.Example
I am writing a component that puts a message in a role=status area. Per WAI, the procedure to test this is:
The component looks something like:
The test that I wrote naively using
rerender
looks like this:Expected behavior
The test passes
Actual behavior
The test fails, because after the
rerender
, thestatus
DOM element still has no text content, because it was unmounted and a new one was created.Workarounds / alternatives considered
I've tried out the following alternatives, none of which feel super ideal. I'd be curious if you had any others!
Re-query elements
The test will pass if I re-query the DOM elements. I dislike this approach because it does not satisfy the recommended test procedure above.
Interact with Svelte component directly
I can update props on the Svelte component directly. I dislike this approach because:
act
is awkward, but necessary to ensure the component is re-renderedcomponent
:Create a wrapper component for testing
I can create a wrapper testing component that updates the prop on a button click (or similar). I dislike this approach because it bloats my test suite and adds a layer of misdirection between my test and the component that I'm actually testing.
The text was updated successfully, but these errors were encountered: