Skip to content

Latest commit

 

History

History
323 lines (253 loc) · 7.44 KB

T5-ContainerComponents.md

File metadata and controls

323 lines (253 loc) · 7.44 KB

Testing Lab 5: Container Components

Objectives

  • Test Setup
  • Test the Loading Indicator Displays
  • Test the Projects Display
  • Test the More Button Displays
  • Test the Error Displays

Steps

Test Setup

  1. Create the file src\projects\__tests__\ProjectsPage-test.tsx.

  2. Add the setup code below to test the component.

    src\projects\__tests__\ProjectsPage-test.tsx

    import React from 'react';
    import { MemoryRouter } from 'react-router-dom';
    import { Provider } from 'react-redux';
    import { store } from '../../state';
    import ProjectsPage from '../ProjectsPage';
    import {
      render,
      screen,
      waitForElementToBeRemoved,
    } from '@testing-library/react';
    
    describe('<ProjectsPage />', () => {
      function renderComponent() {
        render(
          <Provider store={store}>
            <MemoryRouter>
              <ProjectsPage />
            </MemoryRouter>
          </Provider>
        );
      }
    
      test('should render without crashing', () => {
        renderComponent();
        expect(screen).toBeDefined();
      });
    });
  3. Verify the initial test passed.

    PASS  src/projects/__tests__/ProjectsPage-test.tsx
    

Test the Loading Indicator Displays

  1. Test that the loading indicator displays when the component initially renders.

    src\projects\__tests__\ProjectsPage-test.tsx

    import React from 'react';
    import { MemoryRouter } from 'react-router-dom';
    import { Provider } from 'react-redux';
    import { store } from '../../state';
    import ProjectsPage from '../ProjectsPage';
    import {
    render,
    screen,
    waitForElementToBeRemoved,
    } from '@testing-library/react';
    
    describe('<ProjectsPage />', () => {
    function renderComponent() {
       render(
          <Provider store={store}>
          <MemoryRouter>
             <ProjectsPage />
          </MemoryRouter>
          </Provider>
       );
    }
    ...
    
    +  test('should display loading', () => {
    +    renderComponent();
    +    expect(screen.getByText(/loading/i)).toBeInTheDocument();
    +  });
    
    
    });
  2. Verify the test passed.

    PASS  src/projects/__tests__/ProjectsPage-test.tsx
    

Test the Projects Display

  1. Open a command prompt (Windows) or terminal (Mac).

  2. Change the current directory to code\keeptrack.

  3. Run one of the following sets of commands to install Mock Service Worker to mock the HTTP requests.

    $ npm install msw --save-dev
    # or
    $ yarn add msw --dev
    
  4. Export the url used in the component from the projectAPI.ts file.

    src\projects\projectAPI.ts

    import { Project } from './Project';
    
    const baseUrl = 'http://localhost:4000';
    - const url = `${baseUrl}/projects`;
    + export const url = `${baseUrl}/projects`;
    ...
  5. Add the setup code to mock the requests.

    src\projects\__tests__\ProjectsPage-test.tsx

    import React from 'react';
    import { MemoryRouter } from 'react-router-dom';
    import { MOCK_PROJECTS } from '../MockProjects';
    import { Provider } from 'react-redux';
    import { store } from '../../state';
    import ProjectsPage from '../ProjectsPage';
    import {
    render,
    screen,
    waitForElementToBeRemoved,
    } from '@testing-library/react';
    + import { rest } from 'msw';
    + import { setupServer } from 'msw/node';
    + import { url as projectsUrl } from '../projectAPI';
    
    + // declare which API requests to mock
    + const server = setupServer(
    +   // capture "GET http://localhost:3000/projects" requests
    +   rest.get(projectsUrl, (req, res, ctx) => {
    +     // respond using a mocked JSON body
    +     return res(ctx.json(MOCK_PROJECTS));
    +   })
    + );
    
    describe('<ProjectsPage />', () => {
    function renderComponent() {
       render(
          <Provider store={store}>
          <MemoryRouter>
             <ProjectsPage />
          </MemoryRouter>
          </Provider>
       );
    }
    
    +  beforeAll(() => server.listen());
    +  afterEach(() => server.resetHandlers());
    +  afterAll(() => server.close());
    
    test('should render without crashing', () => {
       renderComponent();
       expect(screen).toBeDefined();
    });
    
    test('should display loading', () => {
       renderComponent();
       expect(screen.getByText(/loading/i)).toBeInTheDocument();
    });
    
    
    });
  6. Test that the projects display after the mocked data is returned.

    src\projects\__tests__\ProjectsPage-test.tsx

    ...
    
    describe('<ProjectsPage />', () => {
    function renderComponent() {
       render(
          <Provider store={store}>
          <MemoryRouter>
             <ProjectsPage />
          </MemoryRouter>
          </Provider>
       );
    }
    
    beforeAll(() => server.listen());
    afterEach(() => server.resetHandlers());
    afterAll(() => server.close());
    
    ...
    
    +  test('should display projects', async () => {
    +    renderComponent();
    +    expect(await screen.findAllByRole('img')).toHaveLength(
    +      MOCK_PROJECTS.length
    +    );
    +  });
    
    
    });
    
  7. Verify the test passed.

    PASS  src/projects/__tests__/ProjectsPage-test.tsx
    

Test the More Button Displays

  1. Test that the More button displays after the projects have loaded.

    src\projects\__tests__\ProjectsPage-test.tsx

    ...
    import {
    render,
    screen,
    waitForElementToBeRemoved,
    } from '@testing-library/react';
    ...
    
    describe('<ProjectsPage />', () => {
    ...
    
    +  test('should display more button', async () => {
    +    renderComponent();
    +    expect(
    +      await screen.findByRole('button', { name: /more/i })
    +    ).toBeInTheDocument();
    +  });
    +
    +  // this tests the same as the last test but demonstrates
    +  // what find* methods are doing
    +  test('should display more button with get', async () => {
    +    renderComponent();
    +    await waitForElementToBeRemoved(() => screen.getByText(/loading/i));
    +    expect(screen.getByRole('button', { name: /more/i })).+toBeInTheDocument();
    +  });
    
    });
    
  2. Verify the test passed.

    PASS  src/projects/__tests__/ProjectsPage-test.tsx
    

Test the Error Displays

  1. Test that a custom error displays when a server error is returned.

    src\projects\__tests__\ProjectsPage-test.tsx

    ...
    import {
    render,
    screen,
    waitForElementToBeRemoved,
    } from '@testing-library/react';
    ...
    
    describe('<ProjectsPage />', () => {
    ...
    
    +  test('should display custom error on server error', async () => {
    +    server.use(
    +      rest.get(projectsUrl, (req, res, ctx) => {
    +        return res(ctx.status(500, 'Server error'));
    +      })
    +    );
    +    renderComponent();
    +
    +    expect(
    +      await screen.findByText(/There was an error retrieving the project(s)./i)
    +    ).toBeInTheDocument();
    +  });
    
    });
    
  2. Verify the test passed.

    PASS  src/projects/__tests__/ProjectsPage-test.tsx
    

✔ You have completed Testing Lab 5