dánwòdánwò

Test API

test

Declares tests, their invariants, saved sessions and fresh values; what a *.danwo.ts file is built from.

tests/buy-credits.danwo.ts
import { type StripeFixtures, test as base } from "@danwo/sdk"

import { grantedCredits, paidCredits } from "../src/ledger.ts"

const test = base.extend<StripeFixtures>()

test("buys 500 credits through Stripe Checkout", async ({ app, screen, expect }) => {
  await app.open("/")
  await screen.getByRole("button", { name: "Buy 500 credits" }).click()

  await expect(screen.getByTestId("checkout-total")).toContainText("$5.00")
  /* Paying calls Stripe; readiness waits for the call and plays the webhook it causes. */
  await screen.getByTestId("checkout-pay").click()

  await expect(screen.getByRole("heading", { name: "Thank you for your purchase" })).toBeVisible()
  await expect(screen.getByText(/^Credits: /)).toHaveText("Credits: 500")
}).invariant(async ({ app, stripe, expect }) => {
  // Whichever way the purchase went, the shop grants exactly the credits Stripe was paid for.
  expect(await grantedCredits(app.baseUrl, "u1")).toBe(await paidCredits(stripe, "u1"))
})

test

value

TestAPI<DanwoFixtures>

test typed with danwo's fixtures; the same runtime function as the runner's.

TestAPI

interface

extends Declare<F>

test: declares a test (test(title, body)), with only, skip, describe, the hooks, use, session and extend on it.

MemberDescription
only: Declare<F>
skip: SkipCall<F>
describe: DescribeCall
beforeEach: (fn: TestBody<F>) => void
afterEach: (fn: TestBody<F>) => void
beforeAll: (fn: TestBody<SuiteFixtures>) => void
afterAll: (fn: TestBody<SuiteFixtures>) => void
use: (options: UseOptions) => voidApplies options to every test of the enclosing describe block, or of the file.
session: (name: string, definition: SessionDefinition<F & SessionExtras>) => voidDefines a saved session for this worker; tests start in it with test.use({ session: name }) or { session: name } in their options. Names are per worker: the config's sessions and every file share them.
extend: <T extends object>(definitions?: FixtureDefinitions<T, F>) => TestAPI<F & T>A test whose bodies also receive T, set up by definitions or by the environment.

TestCase

interface

The value test(...) returns, to attach what must hold whichever way the body went.

MemberDescription
invariant(fn: TestBody<F>): TestCase<F>

TestOptions

interface

Options of one test: test(title, options, body).

MemberDescription
retries?: numberExtra attempts after a failure; overrides the config's retries.
timeout?: numberMilliseconds the body (and its invariant) may take; overrides the config's timeout.
skip?: boolean | stringSkip the test: true, or the reason to report.
session?: string | falseStart signed in: the saved session of this name (see session()), or false to start signed out where an enclosing test.use names one.
concurrent?: numberFor danwo matrix: also run the test by this many people at once (2 or more), each in a browser of their own against the same app, and judge the run once by its invariant. For tests that race over shared state, such as two buyers and the last item in stock.

SessionDefinition

type

| SessionSetup<F> | { readonly setup: SessionSetup<F>; readonly check?: SessionSetup<F> }

A saved session: setup runs once per worker, its browser state (cookies, localStorage, IndexedDB) is kept, and every test that uses the session starts from that state. When the environment resets, the state is dropped and setup runs again on next use. check, if given, runs at the start of each test that reuses the state and throws when the state no longer works (say, a page that should show the signed-in user); the session is then set up afresh.

SessionSetup

type

(fixtures: F) => unknown

Signs in (or reaches whatever state the session stands for) in a fresh browser.

unique

function

unique(value: string): Unique

Marks value as fresh on every run: a recorded step replays with the value of this run.

On this page

Run it on every pull request

A GitHub check and one comment per pull request, with the flight records attached.

Set up CI