0

In my Svelte application I'm trying to test using svelte-testing-library that an element is deleted when a specific API request (using msw) succeeds, but not when it returns an error.

Checking the happy path is easy using

const el = await screen.findByText(/foo/);
await waitForElementToBeRemoved(el);

But what is the "correct" way to check that the element is not removed when the request fails? I could add a custom setTimeout(...) but that doesn't seem like the most optimal solution.

Is there a way I could easily ensure that the request has been completed and handled before making the assertion?

Foo.svelte

<script>
  let deleted = false;

  const deleteFoo = () => {
    window
      .fetch(`/foo`, {
        method: 'DELETE',
      })
      .then((res) => {
        if (res.ok) {
          deleted = true;
        }
      });
  };
</script>

{#if !deleted}
  <button on:click={deleteFoo}>delete</button>
{/if}

Foo.spec.js

import {render, fireEvent, waitForElementToBeRemoved} from '@testing-library/svelte';
import {server, rest} from './server';
import Foo from './Foo';

test('button hidden on success', async () => {
  server.use(
    rest.delete('/foo', async (req, res, ctx) => {
      return res(ctx.status(200));
    })
  );
  const {getByText, getByRole} = render(Foo, {});

  const btn = getByText('delete');
  fireEvent.click(btn);

  await waitForElementToBeRemoved(btn);
});

test('button visible on error', async () => {
  server.use(
    rest.delete('/foo', async (req, res, ctx) => {
      return res(ctx.status(500));
    })
  );
  const {getByText, getByRole} = render(Foo, {});

  const btn = getByText('delete');
  fireEvent.click(btn);

  await new Promise((r) => setTimeout(r, 10));
  await getByText('delete');
});
Oskar Persson
  • 6,605
  • 15
  • 63
  • 124

1 Answers1

0

I could envision some test where if the element is ever removed after that the test fails, but then what is the success case?

I think you have to re-frame the goal of your test a bit. So, for example, here are some ways you could approach it:

  1. As you've alluded, test that after a failed request, the element is not removed within X seconds - using a delay to check.
  2. Test that after a failed request, the element is not removed before some event - that could be end of app lifecycle , the next user interaction, etc. Then, perhaps you could listen for whatever event(s) you pick.

The time delay seems simplest to me. But, whatever you decide, I think you have to define it first - otherwise, it's too non-specific to test - eg. the element is not removed (for the lifecycle of the app? until it's removed for some other legitimate reason?).

Chris
  • 359
  • 1
  • 8