1

I have built a ReactJS application using Vite, and I am testing my application using Vitest.

I make heavy usage of react-query within my application. For mocking network requests during testing, I utilize MSW.

I am dealing with a situation where network requests which are certainly executed by code in the first test do not fail until the second test, and I am not sure how to prevent this from happening. It certainly seems to be a race condition, since requests are executed asynchronously while the application is rendered during the first test, and it seems as if some are inevitably "interrupted" when the second test begins and this consistently results in errors being logged (even though both tests pass)

describe("Test the view", () => {
  beforeEach(() => {
    cleanup();
    server.use(...);
  });

  it("DEBUG Handles when rendered with a malformed uuid",
    async () => {
      const uuid= "fail";

      consoleErrorSpy.mockImplementation(() => {
        return;
      });
      server.use(...);
      render(wrappedDetails(uuid));

      await waitFor(
        () => {
          expect(
            screen.getByText("Encountered an error while fetching")
          ).toBeInTheDocument();
        },
        { timeout: 10000 }
      );
    },
    { timeout: 10000 }
  );

  it("DEBUG Displays the details that it is supposed to", async () => {
    const uuid= faker.datatype.uuid();

    render(wrappedDetails(uuid));
    server.use(...);

    await waitFor(() => {
      expect(screen.getAllByRole("heading", { level: 3 }).length).toBe(1);
    });
  });
});

The wrappedDetails that both tests render is like so:

function wrappedDetails(uuid: string) {
  return (
    <MemoryRouter initialEntries={["/things/" + uuid]}>
      <QueryClientProvider client={queryClient}>
        <GenericToastProvider>
          <Routes>
            <Route path="/things/:uuid" element={<ThingDetails />}></Route>
          </Routes>
        </GenericToastProvider>
      </QueryClientProvider>
    </MemoryRouter>
  );
}

Unavoidably I end up with the following output:

> my-ui@0.0.0 qtest
> VITE_TESTING=true vitest run "-t" "DEBUG" "--no-threads"


 RUN  v0.29.3 /path/to/tests

stderr | src/tests/DetailsView.test.tsx > Test the Details view > Displays the details that it is supposed to
GET /api/thing/fail/task-definitions/ net::ERR_FAILED
GET /api/thing/fail/tasks/ net::ERR_FAILED

stderr | unknown test
Error: Error: connect ECONNREFUSED 127.0.0.1:3000
    at Object.dispatchError (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:63:19)
    at Request.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:655:18)
    at Request.emit (node:events:539:35)
    at ClientRequest.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:121:14)
    at ClientRequest.emit (node:events:527:28)
    at Socket.socketErrorListener (node:_http_client:454:9)
    at Socket.emit (node:events:527:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) undefined
Error: Error: connect ECONNREFUSED 127.0.0.1:3000
    at Object.dispatchError (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:63:19)
    at Request.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:655:18)
    at Request.emit (node:events:539:35)
    at ClientRequest.<anonymous> (/home/username/manager-ui/project-manager-ui/node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:121:14)
    at ClientRequest.emit (node:events:527:28)
    at Socket.socketErrorListener (node:_http_client:454:9)
    at Socket.emit (node:events:527:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) undefined

 ✓ src/tests/thingDetailsView.test.tsx (41) 651ms

 Test Files  1 passed | 9 skipped (10)
      Tests  2 passed | 118 skipped (120)
   Start at  16:13:28
   Duration  9.43s (transform 186ms, setup 2.68s, collect 5.59s, tests 651ms)

Of particular note are the lines:

stderr | src/tests/DetailsView.test.tsx > Test the Details view > Displays the details that it is supposed to
GET /api/thing/fail/task-definitions/ net::ERR_FAILED
GET /api/thing/fail/tasks/ net::ERR_FAILED

...These are identified as happening during the second test but the second test makes no use of a uuid "fail" (that is the first test) which is what these failing requests are clearly based on, i.e. /api/thing/fail/task-definitions/ and /api/thing/fail/tasks/ and I am running out of ideas of how to make this stop.

I understand if clarification is needed in order to be able to help. I will respond quickly to any questions asked...

UPDATE 1 - 3/23/2023

A commenter asked whether I was resetting the server handlers after each test, and the answer is that yes, I am. I have the following simple setup.ts file configured:

// Polyfill "window.fetch" used in the React component.
import "whatwg-fetch";
import "@testing-library/jest-dom";

import { server } from "../mocks/server";

beforeAll(() => {
  server.listen();
});

afterEach(() => {
  server.resetHandlers();
});

afterAll(() => {
  server.close();
});
pooley1994
  • 723
  • 4
  • 16
  • 1
    Are you resetting the server handlers after each test? – Tomas Vancoillie Mar 23 '23 at 06:25
  • Hi @TomasVancoillie, thanks for reaching out. I have included an update above to address your question but the short answer is "yes, I am" – pooley1994 Mar 23 '23 at 21:42
  • You probably should [turn off network error logging](https://tanstack.com/query/v4/docs/react/guides/testing#turn-off-network-error-logging) as stated in the docs. – ivanatias Mar 23 '23 at 21:59
  • Interesting thought @ivanatias, but I attempted that and the logs would appear anyways. It seems the logs are coming from JSDOM not react-query, so what I really need would be a way to reset JSDOM in between tests that are in the same file, whereas the only method I could find to reset JSDOM was to break tests apart into individual files which quickly becomes unwieldy. – pooley1994 Mar 23 '23 at 22:11
  • This question/answer seems to be related. It's about the sequence of setup: https://stackoverflow.com/q/73513646/14072498 – Roar S. Mar 26 '23 at 12:51
  • 1
    Thanks @RoarS. I am currently calling `server.listen()` in the `beforeAll` as part of a setup file, and so I think I am already following the advice from that answer. – pooley1994 Mar 27 '23 at 14:09

0 Answers0