Skip to content

Latest commit

 

History

History
244 lines (180 loc) · 5.24 KB

README.md

File metadata and controls

244 lines (180 loc) · 5.24 KB

Testing - front-end web technology

Verify that your UI works, automated.

Please read:

Questions for you

  • How many of you have written at least 5 unit tests (in whatever language) before?
  • How many of you have mocked a dependency while unit testing?

Why is automated testing with Vitest and Testing Library exciting?

  • Focus on testing from user point of view
  • Good support for modules, TypeScript, JSX
  • Fast and good debugging support
  • Widely used / fast adoption, active and friendly community

Setup

  • jsdom to simulate browser in Node.js
  • jest-dom with additional matchers
  • setup file
  • cleanup

Vitest

  • describe
  • it
  • expect, matchers
  • run / watch
  • coverage
  • before / after
  • mocking modules
  • mocking functions, like fetch

Testing Library

  • setup
  • render
  • screen
  • queries
  • click
  • type

Getting Started

Testing app from first section of this course: Getting Started

  • Install deps
npm install vitest jsdom
npm install @testing-library/react @testing-library/user-event @testing-library/jest-dom
  • Configure Vitest in vite.config.ts:
/// <reference types="vitest" />
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  test: {
    environment: "jsdom",
    setupFiles: ["vitest.setup.ts"],
  },
});
  • Configure Testing Library and jest-dom in vitest.setup.ts:
import '@testing-library/jest-dom/vitest';
import { cleanup } from "@testing-library/react";
import { afterEach } from "vitest";

afterEach(cleanup);
  • Configure jest-dom in tsconfig.json:
  "include": ["src", "./vitest.setup.ts"],
  • Write test for initial App render in App.test.tsx:
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import App from "./App";

describe(App.name, () => {
  it("should render", () => {
    render(<App />);
    expect(screen.getByLabelText("Artist name:")).toBeInTheDocument();
  });
});
  • Run Vitest
npx vitest
  • View coverage
npx vitest --run --coverage
# then open coverage/index.html
const form = e.target as HTMLFormElement;
const formElements = form.elements as typeof form.elements & {
  artist: { value: string };
};
const artist = encodeURIComponent(formElements.artist.value);
<form onSubmit={handleSubmit} aria-label="search">
  • Write test for AlbumPicker in App.test.tsx:
describe(AlbumPicker.name, () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("should show search results", async () => {
    const user = userEvent.setup();
    const mockFetch = vi.spyOn(window, "fetch").mockImplementation(async () => {
      return {
        json: async () => mockResponse,
      } as Response;
    });

    render(<AlbumPicker />);

    const artistInput = screen.getByLabelText("Artist name:");
    await user.type(artistInput, "rihanna");
    const form = screen.getByRole("form", { name: "search" });
    fireEvent.submit(form);

    await screen.findByText("A Girl Like Me");

    expect(mockFetch).toHaveBeenCalledWith(
      "https://musicbrainz.org/ws/2/release?fmt=json&query=artist:rihanna"
    );
  });
});

Diagram

Vitest, jsdom, React

Debugging

View the page in a browser at specific points in your test with vitest-preview.

  • Install and run vitest-preview:
npm install vitest-preview
npx vitest-preview
  • Add to test to display in vitest-preview:
import { debug } from "vitest-preview";
// ....
    await screen.findByText("A Girl Like Me");
    debug();

Run the test and see the result in the browser window opened by vitest-preview:

npx vitest --run

Continuous Integration

Run tests on every push.

Add line inside "scripts" in package.json:

"test": "tsc && vitest --run --coverage && vite build"

If your repo is on GitHub, create this .github/workflows/ci.yml file:

name: CI

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - name: Use Node.js
        uses: actions/setup-node@v1
        with:
          node-version: "18"
      - run: npm ci
      - run: npm test

Push to GitHub and see the result of the test.

Next time

Forms.