dánwòdánwò

Test API

screen and Locator

Finding elements the way a user names them, acting on them, and the app and mail handles beside them.

tests/storefront.danwo.ts
import { test } from "@danwo/sdk"

test("shows the credits offer", async ({ app, screen, expect }) => {
  await app.open("/")
  await expect(screen.getByRole("button", { name: "Buy 500 credits" })).toBeVisible()
})

screen.getBy… finds elements the way a user names them; actions need exactly one match. Prefer getByRole with a name, then getByLabel, getByText, getByTestId.

Screen

interface

Finds elements the way a user names them.

MemberDescription
getByRole(role: AriaRole, options?: RoleOptions): Locator
getByLabel(text: TextMatch, options?: TextOptions): Locator
getByPlaceholder(text: TextMatch, options?: TextOptions): Locator
getByText(text: TextMatch, options?: TextOptions): Locator
getByDisplayValue(value: TextMatch): LocatorAn input, textarea or select whose current value is value (whole, unless a RegExp).
getByTestId(id: TextMatch): LocatorBy the data-testid attribute.

Locator

interface

extends Screen

Some elements on the page, found again on every use. Actions need exactly one; reads of one element (text, value, state) do too.

MemberDescription
click: ActionActions that take no input; each waits for the element to be ready.
tap: Actionclick by its mobile name; the same action on a web page.
clear: Action
check: Action
uncheck: Action
hover: Action
fill(value: string | Secret, options?: ActionOptions): Promise<void>Types value in place of what the field holds; a secret's value never reaches a record.
press(key: string, options?: ActionOptions): Promise<void>Presses a key such as "Enter" or "Control+A" with the element focused.
setInputFiles(files: string | readonly string[], options?: ActionOptions): Promise<void>Puts files into a file input (or the file picker the element opens), by the names the session offers them under (files in its options), never by path.
dragTo(target: Locator, options?: ActionOptions): Promise<void>Drags this element and drops it on target.
selectOption(option: string | readonly string[], options?: ActionOptions): Promise<void>Selects options by value or label.
waitFor(options?: WaitOptions): Promise<void>Waits for the element to become visible, or another state.
textContent: Read<string | null>
innerText: Read<string>
inputValue: Read<string>A field's current value; refuses password fields.
getAttribute(name: string, options?: ReadOptions): Promise<string | null>
isVisible(): Promise<boolean>Reads that answer at once, without waiting for the element.
isHidden(): Promise<boolean>
isEnabled: Read<boolean>Whether the single matched element is enabled, disabled or checked.
isDisabled: Read<boolean>
isChecked: Read<boolean>
count(): Promise<number>
all(): Promise<Locator[]>One locator per element matched right now.
allTextContents(): Promise<string[]>
first(): Locator
last(): Locator
nth(index: number): Locator
filter(options: FilterOptions): Locator
or(other: Locator): LocatorThe elements either locator finds, in page order: getByRole("button", { name: "Save" }) .or(getByText("Saved")) waits for whichever shows. An action still needs exactly one.
and(other: Locator): LocatorThe elements both locators find: getByRole("button").and(getByTestId("pay")).

App

interface

The app as a test sees it.

MemberDescription
baseUrl: stringThe app's base URL, as the session was given it.
open(path?: string): Promise<void>Opens path resolved against the base URL, or the base URL itself.

SessionMail

interface

The mail the app sent, as a test reads it.

MemberDescription
latest(to: string): MailMessage | undefinedThe newest email to to, if one arrived.
code(to: string, options?: { readonly digits?: number }): Promise<string>The code in the newest email to to, waiting for the email when it has not arrived yet.
link(to: string, options?: { readonly match?: string }): Promise<string>A link in the newest email to to: the first, or the one whose text or URL has match.
open(to: string): Promise<void>Shows the newest email to to in the active tab, to click its links.

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