mcpField
F
frontend-testing

frontend-testing

github.com/exceptionlessTesting & quality2.5k42 installsUpdated 1d ago
Repository

About frontend-testing

A frontend testing skill for teams using Vitest and @testing-library/svelte. It sets out test placement, TDD and AAA practices, accessible query priorities, and module mocking examples.

Key features

  1. 01Vitest and Testing Library setup
  2. 02Co-located test file conventions
  3. 03TDD and Arrange-Act-Assert patterns
  4. 04Accessible query selection order
  5. 05Module mocking examples

Use cases

  1. 01Writing Svelte component tests
  2. 02Adding tests while fixing bugs
  3. 03Choosing accessible test queries

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/exceptionless/exceptionless --skill frontend-testing

After installing, type/frontend-testingin Claude Code to confirm it loaded.

Details

From the project README

Frontend Testing

Documentation: vitest.dev | testing-library.com

Framework & Location

  • Framework: Vitest + @testing-library/svelte
  • Location: Co-locate with code as .test.ts or .spec.ts
  • TDD workflow: When fixing bugs or adding features, write a failing test first

AAA Pattern

Use explicit Arrange, Act, Assert regions:

import { describe, expect, it } from "vitest";

describe("Calculator", () => {
    it("should add two numbers correctly", () => {
        // Arrange
        const a = 5;
        const b = 3;

        // Act
        const result = add(a, b);

        // Assert
        expect(result).toBe(8);
    });
});

Testing with Spies

import { beforeEach, describe, expect, it, vi } from "vitest";
import { CachedPersistedState } from "./cached-persisted-state.svelte";

describe("CachedPersistedState", () => {
    beforeEach(() => {
        vi.clearAllMocks();
    });

    it("should return cached value without reading storage repeatedly", () => {
        // Arrange
        const getItemSpy = vi.spyOn(Storage.prototype, "getItem");
        localStorage.setItem("test-key", "value1");
        const state = new CachedPersistedState("test-key", "default");
        getItemSpy.mockClear();

        // Act
        const val1 = state.current;
        const val2 = state.current;

        // Assert
        expect(val1).toBe("value1");
        expect(val2).toBe("value1");
        expect(getItemSpy).not.toHaveBeenCalled();
    });
});

Query Selection Priority

Use accessible queries (not implementation details):

  1. screen.getByRole("button", { name: /submit/i }) — Role-based (preferred)
  2. screen.getByLabelText("Email address") — Label-based
  3. screen.getByText("Welcome back") — Text-based
  4. screen.getByTestId("complex-chart") — Test ID (fallback)
  5. ❌ screen.getByClassName("btn-primary") — Never use implementation details

Mocking Modules

import { vi, describe, it, beforeEach, expect } from "vitest";
import { render, screen } from "@testing-library/svelte";

vi.mock("$lib/api/organizations", () => ({
    getOrganizations: vi.fn(),
}));

import { getOrganizations } from "$lib/api/organizations";
import OrganizationList from "./organization-list.svelte";

describe("OrganizationList", () => {
    beforeEach(() => {
        vi.clearAllMocks();
    });

    it("displays organizations from API", async () => {
        // Arrange
        vi.mocked(getOrganizations).mockResolvedValue([{ id: "1", name: "Org One" }]);

        // Act
        render(OrganizationList);

        // Assert
        expect(await screen.findByText("Org One")).toBeInTheDocument();
    });
});

Comments

Markdown supported