Test API
test
Declares tests, their invariants, saved sessions and fresh values; what a *.danwo.ts file is built from.
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.
| Member | Description |
|---|---|
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) => void | Applies options to every test of the enclosing describe block, or of the file. |
session: (name: string, definition: SessionDefinition<F & SessionExtras>) => void | Defines 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.
| Member | Description |
|---|---|
invariant(fn: TestBody<F>): TestCase<F> |
TestOptions
interface
Options of one test: test(title, options, body).
| Member | Description |
|---|---|
retries?: number | Extra attempts after a failure; overrides the config's retries. |
timeout?: number | Milliseconds the body (and its invariant) may take; overrides the config's timeout. |
skip?: boolean | string | Skip the test: true, or the reason to report. |
session?: string | false | Start signed in: the saved session of this name (see session()), or false to start signed out where an enclosing test.use names one. |
concurrent?: number | For 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) => unknownSigns in (or reaches whatever state the session stands for) in a fresh browser.
unique
function
unique(value: string): UniqueMarks value as fresh on every run: a recorded step replays with the value of this run.