### Install and run Lightning (Chinese quick start) Source: https://github.com/zixiao-labs/lightning/blob/main/website/index.html Install and run Lightning tests, watch, typecheck, and bench. Requires Node.js ≥22.12.0. ```bash pnpm add -D @lightning-js/lightning pnpm exec lightning run pnpm exec lightning watch pnpm exec lightning run --typecheck pnpm exec lightning bench ``` -------------------------------- ### Install and run Lightning tests Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Install Lightning and run tests once or in watch mode. Bare `lightning` watches in an interactive terminal and runs once in CI/non-TTY; use `run`, `watch`, `--watch` or `--no-watch` to choose explicitly. ```sh pnpm add -D @lightning-js/lightning pnpm exec lightning run pnpm exec lightning watch ``` -------------------------------- ### Install and run Lightning tests Source: https://github.com/zixiao-labs/lightning/blob/main/website/index.html Install Lightning and run or watch tests. Requires Node.js ≥22.12.0. ```bash pnpm add -D @lightning-js/lightning pnpm exec lightning run pnpm exec lightning watch ``` -------------------------------- ### Install DOM environments and run browser tests Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Installs DOM environments and Playwright, then runs or watches Lightning tests in browser mode. ```sh pnpm add -D jsdom # or: pnpm add -D happy-dom pnpm add -D playwright pnpm exec playwright install chromium pnpm exec lightning run --browser pnpm exec lightning watch --browser ``` -------------------------------- ### Development commands for install, typecheck, test, and docs Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Development workflow commands for installing dependencies and running type checks, tests, benchmarks, and documentation generation. The browser integration test requires Chromium to be installed. ```sh pnpm install --frozen-lockfile pnpm typecheck pnpm test pnpm test:runtime pnpm test:integration pnpm test:browser:integration # requires installed Chromium pnpm test:frameworks pnpm test:types pnpm test:bench pnpm docs ``` -------------------------------- ### Example: test with failed and finished cleanup Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/context.md Shows using onTestFailed and onTestFinished inside a test body. onTestFailed runs only on failure, onTestFinished always runs. The example starts a server, registers cleanup to dump logs on failure and stop the server always, then asserts a ping response. ```typescript import { onTestFinished, onTestFailed } from "@lightning-js/lightning"; test("hypothesis with failed and finished cleanup", async ({ onTestFinished, onTestFailed, expect }) => { const server = await startServer(); onTestFailed(() => server.dumpLogs()); // only on failure onTestFinished(() => server.stop()); // always expect(await server.ping()).toBe("pong"); }); ``` -------------------------------- ### Module mocks example Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/vi.md Shows how to mock a module with vi.mock and verify the mock is used when importing. Also checks vi.isMockFunction on a vi.fn() mock. ```typescript import { vi } from "@lightning-js/lightning"; vi.mock("./config", () => ({ apiKey: "test-key" })); test("mocked module", async () => { const config = await import("./config"); expect(config.apiKey).toBe("test-key"); expect(vi.isMockFunction(vi.fn())).toBe(true); }); ``` -------------------------------- ### Select environment with @lightning-environment directive Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Sets the test environment for a single file with a directive at the top. The example uses jsdom and asserts on document.createElement. Supported environments are node, jsdom, happy-dom, and edge-runtime; install the chosen DOM emulator in the consuming project. ```TypeScript // @lightning-environment jsdom import { expect, test } from "@lightning-js/lightning"; test("has a document", () => { expect(document.createElement("button").tagName).toBe("BUTTON"); }); ``` -------------------------------- ### Spy and implementations example Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/vi.md Shows how to use spyOn to spy on a method, mock its return value, and restore it. Demonstrates that mockReturnValue overrides the original implementation and mockRestore reverts it. ```typescript import { vi, fn, spyOn } from "@lightning-js/lightning"; test("spy and implementations", () => { const math = { add: (a: number, b: number) => a + b }; const spy = spyOn(math, "add"); expect(math.add(1, 2)).toBe(3); spy.mockReturnValue(42); expect(math.add(1, 2)).toBe(42); spy.mockRestore(); expect(math.add(1, 2)).toBe(3); }); ``` -------------------------------- ### Lightning CLI usage examples Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/cli.md These commands illustrate common CLI usage: running a named project with JSON output, watching tests with snapshot updates, running a CI shard with coverage, and benchmarking against a baseline with a regression threshold. ```sh lightning run --project unit --reporter json --output-file report.json ``` ```sh lightning watch -t "auth" --environment jsdom # press u inside watch to update snapshots for the next rerun ``` ```sh lightning run --shard 2/4 --coverage --coverage-provider v8 ``` ```sh lightning bench --baseline bench.json --compare bench.json --regression-threshold 5 ``` -------------------------------- ### vi.when Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/when.md Installs argument-based behaviors on a mock, Vitest 5 style. Behaviors match FIFO (first registered arg-set wins); actions within a behavior stack LIFO. ```APIDOC ## `vi.when(mock, options?)` ### Description Installs argument-based behaviors on a mock, Vitest 5 style. Behaviors match FIFO (first registered arg-set wins); actions within a behavior stack LIFO. ### Method `when` ### Signature ```ts when(mock: MockInstance, options: WhenOptions = {}): WhenChain ``` ### Parameters - **mock** (`MockInstance`) - Required - The mock function or spy to install behaviors on. - **options** (`WhenOptions`) - Optional - Configuration options. `onUnmatched` can be `"throw"` or a function to handle unmatched calls. ### Return Value Returns a `WhenChain` for chaining behavior definitions. ### Behavior - Behaviors match FIFO (first registered arg-set wins). - Actions within a behavior stack LIFO. - `times` defaults to `Number.POSITIVE_INFINITY`. - Accumulation is additive: each `thenX` appends an action, `thenXOnce` appends an action with `times: 1`. ### Error Handling | Condition | Thrown | |-----------|--------| | `mock` is not a mock (`!mock?._isMockFunction`) | `TypeError("vi.when expects a mock function or spy")` | | Adding an action before `calledWith` (or after disposal) | `Error("Call calledWith before adding an action to vi.when")` | | `ActionOptions.times` not a positive integer (when finite) | `Error("vi.when action times must be a positive integer")` | | `calledWith` on a disposed chain | `Error("vi.when chain has been disposed")` | | `onUnmatched: "throw"` and a call matches nothing | `Error('vi.when: no behavior defined when called with ')` | ### Call Resolution 1. Finds the first behavior whose stored args `deepEqual` the actual call args (asymmetric matchers are honored via `deepEqual`). 2. Takes the **last** action in that behavior with remaining budget (`entry.used < entry.times`) and runs it. 3. Otherwise, if `unmatched === "throw"`, throws the descriptive error; if `unmatched` is a function, calls it; else falls back to the mock's pre-`when` implementation. ### Example ```ts import { expect, vi } from "@lightning-js/lightning"; const fetchUser = vi.fn(async (id: number) => ({ id, name: "unknown" })); vi.when(fetchUser) .calledWith(1) .thenResolve({ id: 1, name: "ada" }) .calledWith(2) .thenThrow(new Error("not found")); vi.when(fetchUser).calledWith(3).thenResolveOnce({ id: 3, name: "once" }); test("conditional responses", async () => { await expect(fetchUser(1)).resolves.toEqual({ id: 1, name: "ada" }); await expect(fetchUser(2)).rejects.toThrow("not found"); await expect(fetchUser(3)).resolves.toMatchObject({ id: 3 }); await fetchUser(3); // second call falls back to the original implementation }); ``` ``` -------------------------------- ### Run Lightning tests with coverage, reporters, and sharding Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Commands for running Lightning tests with coverage, custom reporters, and sharding. Coverage providers are v8 and istanbul; reporters include junit and json with output files. Sharding example uses 1/4. ```sh pnpm exec lightning run --coverage --coverage-provider v8 pnpm exec lightning run --coverage --coverage-provider istanbul pnpm exec lightning run --reporter junit --output-file artifacts/junit.xml pnpm exec lightning run --reporter json --output-file artifacts/results.json pnpm exec lightning run --shard 1/4 ``` -------------------------------- ### Example: toEqual with asymmetric matchers Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/expect.md Shows how to use asymmetric matchers like expect.any, expect.stringMatching, expect.arrayContaining, and expect.objectContaining within toEqual. Also demonstrates expect.anything() with toBe. ```typescript import { expect } from "@lightning-js/lightning"; test("user payload shape", () => { expect(user).toEqual({ id: expect.any(Number), name: expect.stringMatching(/^[A-Z]/), tags: expect.arrayContaining(["admin"]), meta: expect.objectContaining({ plan: "pro" }), }); expect(null).toBe(expect.anything()); }); ``` -------------------------------- ### Fake timers and stubs example Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/vi.md Demonstrates using fake timers with a specific system time, advancing time, and stubbing globals and environment variables. Shows cleanup with unstubAllGlobals, unstubAllEnvs, and useRealTimers in a finally block. ```typescript import { vi } from "@lightning-js/lightning"; test("fake timers", () => { vi.useFakeTimers({ now: new Date(2024, 0, 1) }); const cb = vi.fn(); setTimeout(cb, 500); vi.advanceTimersByTime(500); expect(cb).toHaveBeenCalledTimes(1); expect(vi.getMockedSystemTime()).toEqual(new Date(2024, 0, 1)); vi.stubGlobal("location", { href: "https://example.com" }); vi.stubEnv("FEATURE", "on"); try { expect(globalThis.location.href).toBe("https://example.com"); } finally { vi.unstubAllGlobals(); vi.unstubAllEnvs(); vi.useRealTimers(); } }); ``` -------------------------------- ### Example: task and expect from context Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/context.md Shows accessing task and expect from the TestContext. Asserts the test name and mode from the task object. ```typescript test("task and expect from context", ({ task, expect }) => { expect(task.name).toBe("task and expect from context"); expect(task.mode).toBe("run"); }); ``` -------------------------------- ### Basic test and it usage with expect Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/test.md Shows the minimal imports and usage of test and it from @lightning-js/lightning. The test callback receives an expect object for assertions; the it example demonstrates async support with await. ```ts import { test, it } from "@lightning-js/lightning"; test("adds numbers", ({ expect }) => { expect(1 + 2).toBe(3); }); it("is async", async () => { await Promise.resolve(); }); ``` -------------------------------- ### Add a benchmark with bench Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Declares a benchmark in *.bench.ts files and runs with lightning bench. The example benchmarks JSON.parse and asserts the throughput mean is greater than zero. ```TypeScript import { expect, test } from "@lightning-js/lightning"; test("parse JSON", async ({ bench }) => { const result = await bench("JSON.parse", () => JSON.parse('{"ok":true}'), { time: 100, }).run(); expect(result.throughput.mean).toBeGreaterThan(0); }); ``` -------------------------------- ### Test lifecycle with hooks Source: https://github.com/zixiao-labs/lightning/blob/main/docs/API.md Shows the full lifecycle of a test suite: beforeAll/beforeEach can return cleanup functions that run during teardown (even after failures), while afterEach/afterAll return values are ignored. Use this as a template for organizing setup, teardown, and test cases. ```ts import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, } from "@lightning-js/lightning"; describe("string helpers", () => { beforeAll(() => { // Runs once before this suite. return () => { // Runs during suite teardown, including after failures. }; }); beforeEach(() => { // Runs before each test in this suite. return () => { // Runs during test teardown, including after failures. }; }); test("normalizes a value", () => { expect(" Lightning ".trim()).toBe("Lightning"); }); afterEach(() => { // Runs after each test. Return values are ignored. }); afterAll(() => { // Runs once after this suite. Return values are ignored. }); }); ``` -------------------------------- ### Run development commands Source: https://github.com/zixiao-labs/lightning/blob/main/website/index.html Development commands for typechecking, testing, and benchmarking the Lightning repository. ```bash pnpm typecheck pnpm test pnpm test:runtime pnpm test:integration pnpm test:browser:integration pnpm test:frameworks pnpm test:types pnpm test:bench ``` -------------------------------- ### Import bench and describeBench from @lightning-js/lightning Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/bench.md Import the bench and describeBench functions from the Lightning package to define benchmarks. ```typescript import { bench, describeBench } from "@lightning-js/lightning"; ``` -------------------------------- ### Type-test file example with expectTypeOf Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/type-testing.md Example of a type-test file following the `*.test-d.ts` convention, using `expectTypeOf` to assert parameter and return types. ```typescript // src/types.example.test-d.ts — run with: lightning run --typecheck import { expectTypeOf } from "@lightning-js/lightning"; declare function pick(obj: T, key: K): T[K]; expectTypeOf(pick).parameter(0).toMatchTypeOf>(); expectTypeOf(pick({ a: 1 }, "a")).toEqualTypeOf(); ``` -------------------------------- ### mapJestConfig usage Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/config.md Example usage of mapJestConfig to convert a Jest-style config object into a LightningConfig. ```ts import { mapJestConfig } from "@lightning-js/lightning/config"; const config = mapJestConfig({ rootDir: ".", testMatch: ["/src/**/*.test.ts"], testEnvironment: "jsdom", testTimeout: 10000, }); ``` -------------------------------- ### Benchmark with bench and describeBench.skip Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/bench.md Shows how to define benchmarks with the `bench` function, including setting the number of iterations and using `describeBench.skip` to skip a group of benchmarks. ```ts import { bench, describe, test } from "@lightning-js/lightning"; bench("JSON.parse", () => JSON.parse('{"a":1}'), { iterations: 10_000 }); describeBench.skip("cold storage", () => { bench("empty", () => {}); }); ``` -------------------------------- ### defineConfig usage in lightning.config.ts Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/config.md Example lightning.config.ts using defineConfig to set test include patterns, pool, and timeout. ```ts // lightning.config.ts import { defineConfig } from "@lightning-js/lightning/config"; export default defineConfig({ test: { include: ["test/**/*.test.ts"], pool: "threads", testTimeout: 5000, }, }); ``` -------------------------------- ### vi Mock Helpers Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/vi.md Documentation for the `vi` mock helper object, including the `MockInstance` interface and its methods. ```APIDOC ## `vi` — Mocking, Fake Timers, Stubs, Module Mocks ### Description `vi` is a frozen object of mock helpers; `jest` is an export alias for the same object. `vi.when` is the conditional-mocking API documented in [when.md](when.md). ### Import ```ts import { vi, jest, fn, spyOn, isMockFunction } from "@lightning-js/lightning"; ``` ### Methods #### `vi.fn()` - **Description**: Creates a mock function. - **Returns**: `MockInstance` #### `vi.spyOn()` - **Description**: Creates a spy on an object method. - **Returns**: `MockInstance` #### `vi.isMockFunction()` - **Description**: Checks if a value is a mock function. - **Returns**: `boolean` #### `vi.when` - **Description**: Conditional-mocking API (see [when.md](when.md)). ### `MockInstance` Interface ```ts export interface MockInstance { (...args: Parameters): ReturnType; _isMockFunction: true; mock: MockContext; getMockImplementation(): AnyFunction | undefined; mockImplementation(fn: T): this; mockImplementationOnce(fn: T): this; withImplementation(fn: T, callback: () => R): R; mockReturnThis(): this; mockReturnValue(value: ReturnType): this; mockReturnValueOnce(value: ReturnType): this; mockResolvedValue(value: Awaited>): this; mockResolvedValueOnce(value: Awaited>): this; mockRejectedValue(value: unknown): this; mockRejectedValueOnce(value: unknown): this; mockClear(): this; mockReset(): this; mockRestore(): void; mockName(name: string): this; getMockName(): string; } ``` ### `MockContext` Fields - `calls: unknown[][]` - Arguments per call. - `instances: unknown[]` - Only when called with `new`. - `contexts: unknown[]` - The `this` values. - `invocationCallOrder: number[]` - Global invocation counter. - `results: MockResult[]` - Results of each call. `MockResult = { type: "return" | "throw" | "incomplete"; value: unknown }` ### Method Behaviors | Method | Behavior | |--------|----------| | `mockImplementation(fn)` | Sets the implementation (overrides the `fn()` factory argument). | | `mockImplementationOnce(fn)` | Enqueues an implementation consumed once (FIFO). | | `withImplementation(fn, callback)` | Temporarily replaces implementation/once queue for `callback`; restores in `finally` or after the returned promise settles. | | `mockReturnThis()` | Implementation returns the `this` receiver. | | `mockReturnValue(v)` / `Once(v)` | Implementation / one-shot implementation returning `v`. | | `mockResolvedValue(v)` / `Once(v)` | Implementation / one-shot returning `Promise.resolve(v)`. | | `mockRejectedValue(v)` / `Once(v)` | Implementation / one-shot returning `Promise.reject(v)`. | | `mockClear()` | Empties `calls`/`instances`/`contexts`/`invocationCallOrder`/`results` (keeps implementation). | | `mockReset()` | `mockClear()` + drops implementation, once queue, name ("vi.fn()"), and `vi.when` state. | | `mockRestore()` | `mockReset()` + restores the original property (for spies) or runs the registered restore. | | `mockName(name)` / `getMockName()` | Set / read the display name. | ``` -------------------------------- ### Lightning CLI basic commands Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/cli.md Shows the four primary CLI invocations: bare `lightning` (watch in TTY, run-once otherwise), `lightning run` (run once), `lightning watch` (watch), and `lightning bench` (run Tinybench benchmarks once). ```bash lightning # watch in a TTY, run-once in CI/non-TTY lightning run # always run once and exit lightning watch # always watch lightning bench # run Tinybench benchmarks once ``` -------------------------------- ### when function signature Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/when.md Function signature for vi.when, which installs argument-based behaviors on a mock. Throws TypeError if mock is not a mock function or spy. ```ts export function when(mock: MockInstance, options: WhenOptions = {}): WhenChain ``` -------------------------------- ### defineProject usage in projects array Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/config.md Example config using defineProject to define two projects: unit and dom (with jsdom environment). ```ts import { defineConfig, defineProject } from "@lightning-js/lightning/config"; export default defineConfig({ test: { projects: [ defineProject({ test: { name: "unit", include: ["test/unit/**"] } }), defineProject({ test: { name: "dom", environment: "jsdom", include: ["test/dom/**"] } }), ], }, }); ``` -------------------------------- ### Run and compare benchmarks with lightning bench CLI Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Commands to run benchmarks with a baseline and to compare against a baseline with a regression threshold of 10%. A throughput loss exceeding the threshold fails the run. Measurements are serial and should be compared on controlled hardware. ```sh pnpm exec lightning bench --baseline artifacts/bench.json pnpm exec lightning bench --compare artifacts/bench.json --regression-threshold 10 ``` -------------------------------- ### test / it — Test API Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/test.md Documentation for the `test`/`it` API from the Lightning test runtime, including call signatures, options, and usage examples. ```APIDOC ## `test` / `it` — Test API ### Description Registers a test task into the currently-open suite during file collection. `test` and `it` are the same function object. ### Import ```ts import { test, it } from "@lightning-js/lightning"; ``` ### Type ```ts export interface TestAPI { (name: string): void; (name: string, fn: TestFn, timeout?: number): void; (name: string, options: RunnableOptions, fn?: TestFn): void; skip: TestAPI; only: TestAPI; todo: (name: string, fn?: TestFn) => void; concurrent: TestAPI; sequential: TestAPI; fails: TestAPI; skipIf: (condition: unknown) => TestAPI; runIf: (condition: unknown) => TestAPI; for: (cases: readonly T[]) => (name: string, fn: (value: T, context: import("./context.ts").TestContext) => void | Promise) => void; each: (cases: readonly T[]) => (name: string, fn: TestFactory) => void; retry: (times: number) => TestAPI; repeats: (times: number) => TestAPI; } ``` ### Call Signatures | Signature | Behavior | |-----------|----------| | `test(name)` | Registers a **todo** task (no body). | | `test(name, fn, timeout?)` | Runs `fn` with context; numeric third argument becomes `timeout` (ms). | | `test(name, options, fn?)` | Applies `RunnableOptions`; when `fn` is omitted the test is registered as `todo`. | ### Parameters #### `name` (string) - Required Name of the test. #### `fn` (TestFn) - Optional Test function: `(context: TestContext) => void | Promise`. #### `timeout` (number) - Optional Timeout in milliseconds. Defaults to suite/config default (`testTimeout`, default 5000). #### `options` (RunnableOptions) - Optional Options object with the following fields: | Field | Type | Default | Effect | |-------|------|---------|--------| | `skip` | boolean | false | Task mode becomes `skip` | | `only` | boolean | false | Task mode becomes `only`; sets `hasOnly` | | `todo` | boolean | false | Task mode becomes `todo` | | `fails` | boolean | false | Invert: test passes when its body throws, fails when it does not | | `concurrent` | boolean | false | Run in the concurrent lane when possible | | `sequential` | boolean | false | Force sequential execution under a concurrent parent suite | | `timeout` | number | suite/config default (`testTimeout`, default 5000) | Per-test timeout in ms | | `retry` | number | config `retry` (default 0) | Retries after a failing attempt | | `repeats` | number | config `repeats` (default 1) | Times to repeat the test | ### Mode Precedence `options.skip` → `skip`, `options.todo` → `todo`, `options.only` → `only`, otherwise the mode the API was created with. A test inherits `timeout`/`retry`/`repeats` from its enclosing suite when the suite sets them and the test does not. ### Example ```ts import { test, it } from "@lightning-js/lightning"; test("basic test", (context) => { // test body }); it("todo test"); test("with options", { skip: true }, (context) => { // skipped test }); test("with timeout", (context) => { // test body }, 1000); ``` ``` -------------------------------- ### Register cleanup with onTestFinished Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Registers a cleanup callback that runs after the test whether it passes or fails. The example opens a connection and closes it via onTestFinished. ```TypeScript import { expect, test } from "@lightning-js/lightning"; test("closes a resource after the test", async ({ onTestFinished }) => { const connection = await openConnection(); onTestFinished(() => connection.close()); expect(connection.isOpen()).toBe(true); }); ``` -------------------------------- ### In-test benchmark with bench.compare Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/bench.md Demonstrates in-test benchmarking using `context.bench` to compare two parsers, retrieve results by name, assert completion state, and log throughput. ```ts test("compare two parsers", async ({ bench, expect }) => { const results = await bench.compare( bench("A", () => parseA(input)), bench("B", () => parseB(input), { iterations: 5_000 }), ); const a = results.get("A")!; expect(a.state).toBe("completed"); console.log(a.throughput.mean, "ops/sec"); }); ``` -------------------------------- ### Table-driven tests with test.each Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Runs the same test against multiple sets of arguments. The example uses test.each with an array of tuples and formats the test name with %i placeholders. ```TypeScript import { expect, test } from "@lightning-js/lightning"; test.each([ [1, 2, 3], [5, 8, 13], ])("adds %i and %i", (left, right, expected) => { expect(left + right).toBe(expected); }); ``` -------------------------------- ### Await promise matchers with resolves Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Use await with promise matchers so rejected assertions fail the current test. The example resolves a promise and asserts its value with toEqual. ```TypeScript import { expect, test } from "@lightning-js/lightning"; test("loads a profile", async () => { const profile = Promise.resolve({ id: 7, name: "Ada" }); await expect(profile).resolves.toEqual({ id: 7, name: "Ada" }); }); ``` -------------------------------- ### Benchmark with context bench API and CLI Source: https://github.com/zixiao-labs/lightning/blob/main/website/index.html Benchmark a function with the context bench API and run CLI comparisons. Context comparisons and measurements are serial. Legacy top-level bench and describe.bench remain supported. ```typescript test("parse", async ({ bench, expect }) => { const result = await bench("JSON", () => JSON.parse("{}"), { time: 100 }).run(); expect(result.throughput.mean).toBeGreaterThan(0); }); // *.bench.ts / *.benchmark.ts // lightning bench --baseline baseline.json // lightning bench --compare baseline.json --regression-threshold 10 ``` -------------------------------- ### Scoped behavior with using and Symbol.dispose Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/when.md Example using the `using` statement to automatically dispose the vi.when chain at the end of the block, restoring the mock's original behavior. ```ts test("scoped with Symbol.dispose", () => { const mock = vi.fn(); { using chain = vi.when(mock).calledWith(1).thenReturn("one"); expect(mock(1)).toBe("one"); } // chain disposed here expect(mock(1)).toBeUndefined(); }); ``` -------------------------------- ### describe.each / describe.for Source: https://github.com/zixiao-labs/lightning/blob/main/docs/API.md Creates parameterized test suites from a table of inputs. ```APIDOC ## describe.each / describe.for ### Description Creates parameterized test suites. Each row of the table is used to generate a suite with the given name template. ### Parameters - **table** (array) - Required - An array of argument tuples. - **name** (string) - Required - The suite name template. - **fn** (function) - Required - The suite definition function. ### Example ```ts import { describe, test } from "@lightning-js/lightning"; describe.each([ [1, 2, 3], [2, 3, 5], ])("sum of %i and %i", (left, right, sum) => { test("adds correctly", () => { expect(left + right).toBe(sum); }); }); ``` ``` -------------------------------- ### Type testing example with assertType and expectTypeOf Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/type-testing.md Shows usage of `assertType` for assignability checks and `expectTypeOf` for exact type matching, including a `@ts-expect-error` comment for a failing case. ```typescript import { expectTypeOf, assertType } from "@lightning-js/lightning"; type User = { id: number; name: string }; assertType({ id: 1, name: "ada" }); // @ts-expect-error — missing name assertType({ id: 1 }); expectTypeOf().toMatchTypeOf<{ id: number }>(); expectTypeOf<() => string>().returns.toBeString(); ``` -------------------------------- ### Run tests in browser mode with Playwright Source: https://github.com/zixiao-labs/lightning/blob/main/website/index.html Set up and run browser mode with Playwright. Import DOM helpers from @lightning-js/lightning/browser. Always await userEvent; browser actions use trusted Playwright input. ```bash pnpm add -D playwright pnpm exec playwright install chromium pnpm exec lightning run --browser pnpm exec lightning watch --browser ``` -------------------------------- ### Import lightning from @lightning-js/lightning Source: https://github.com/zixiao-labs/lightning/blob/main/_autodocs/api-reference/programmatic.md Import the lightning function from the package. This is the entry point for the programmatic API. ```ts import { lightning } from "@lightning-js/lightning"; ``` -------------------------------- ### Mock a function and inspect calls with fn Source: https://github.com/zixiao-labs/lightning/blob/main/docs/EXAMPLES.md Creates a mock function with fn and asserts its calls using toHaveBeenCalledWith. The example shows a mock that returns a string and records the call. ```TypeScript import { expect, fn, test } from "@lightning-js/lightning"; test("records calls", () => { const send = fn((message: string) => `sent: ${message}`); expect(send("ready")).toBe("sent: ready"); expect(send).toHaveBeenCalledWith("ready"); }); ``` -------------------------------- ### Configure projects with defineConfig Source: https://github.com/zixiao-labs/lightning/blob/main/README.md Configure multiple projects with inline objects, config files, directories, and glob patterns. Defaults are inherited; `extends: false` opts out. Use `--project unit` or `-p unit` to select a project; parent names select nested children. Reporters run once for the whole invocation, so multi-project JSON is one valid document and JUnit contains all project results. ```ts import { defineConfig } from "@lightning-js/lightning/config"; export default defineConfig({ test: { maxWorkers: 2, projects: [ { test: { name: "unit", include: ["test/unit/**/*.test.ts"] } }, { test: { name: "dom", environment: "jsdom", include: ["test/dom/**/*.test.ts"] } }, "packages/*/lightning.config.ts", ], }, }); ```