3

Here is a sample of my code

// App.js

import React, { Suspense, lazy } from "react";

const Loader = () => <div data-testid="loader">Loading...</div>

const Login = lazy(() => import("./Login"));

function App() {
  return (
    <Suspense fallback={<Loader />}>
      <Login />
    </Suspense>
  );
}

export default App;

// Login.js

import React from 'react';

const Login = () => <div data-testid="login">Login</div>

export default Login
// App.test.js

import React from 'react';
import { render, waitForElementToBeRemoved, cleanup } from '@testing-library/react';
import App from './App';


describe('App when user is not signed in', () => {
  it("should redirect to login page", async () => {
    beforeEach(() => jest.resetAllMocks())
    const { getByTestId, getByText } = render(<App />);
    await waitForElementToBeRemoved(() => getByTestId('loader'))
    const linkElement = getByText(/Login/i);
  
    expect(linkElement).toBeInTheDocument();
  });
})

describe('App with User Logged in as Admin', () => {
  it("redirect to login page", async () => {
    beforeEach(() => {
      // will set local storage for auth token
      // for a logged in user
    })
    let container = document.createElement('div')
    const { getByTestId, getByText } = render(<App />, {
      container
    });
  
    await waitForElementToBeRemoved(() => getByTestId('loader'))
    const linkElement = getByText(/Login/i);
  
    expect(linkElement).toBeInTheDocument();
  });
})

The issue I am having is that I expect to have the loader when I run the second test but it is not there thus throwing an error.

I would like to know why the loader is not rendered in the second test which renders the login page straight away. I suspect the first test is affecting the second test but the question is why.

I created a repl to this issue here. https://repl.it/@tibetegya/Create-React-App

skyboyer
  • 22,209
  • 7
  • 57
  • 64
  • FYI, the repl you posted reproduces how the app in production but not tests, so it couldn't be used to debug the problem. – Estus Flask Jun 28 '20 at 09:47

1 Answers1

0

toBeInTheDocument asserts that the element exists in the document, as the name suggests:

The jest-dom utility library provides the .toBeInTheDocument() matcher, which can be used to assert that an element is in the body of the document, or not. This can be more meaningful than asserting a query result is null.

The component was rendered to detached container element in the second test and doesn't exist in document DOM, so the test fails.

Instead, basic Jest assertions can be used, as the documentation suggests:

expect(linkElement).not.toBeNull()

There may be no reason to use custom container, unless there's a need to test how the component works in detached elements.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565