Skip to content

Working with Elements

await orbit.click("Login");
await orbit.doubleClick("Open");
await orbit.rightClick("File");
await orbit.hover("Menu");

All four accept visible text or any locator. Click actions render a brief red dot at the exact click coordinate, which makes step-debugging and trace screenshots much easier to follow. Disable it per action with await orbit.click("Login", { visualize: false }) if needed.

Use exists() for yes/no checks. Note the { timeout: 0 } trick when you expect absence; otherwise the call waits for the element to appear before giving up:

expect(await orbit.exists(orbit.css(".success"))).toBe(true);
expect(await orbit.exists(orbit.css(".error"), { timeout: 0 })).toBe(false);

For reading text, OrbitTest gives you three readers because “the text of an element” means different things in different situations:

HelperReturnsHidden content
orbit.text(locator)User-facing text: DOM text, form values, ARIA label, title, altMay include ARIA sources
orbit.visibleText(locator)Only the text actually rendered on screenExcluded
orbit.domText(locator)All text in the element treeIncluded
const label = await orbit.visibleText(orbit.css("#save-button"));
expect(label).toBe("Save");
const diagnostic = await orbit.domText(orbit.css("#server-message"));
expect(diagnostic).toContain("Hidden diagnostic id");

visibleText for what users see; domText for what the page contains.

All three trim and normalize whitespace, so you compare against clean strings.

Almost every flaky end-to-end test in the world comes down to the same bug: the test ran faster than the page. The fix is to wait for state, never for time:

// Good: finishes the moment the page is ready
await orbit.waitForText("Dashboard");
await orbit.waitFor(orbit.css(".toast"));
await orbit.waitFor(orbit.getByRole("button", "Save"));
// With a custom budget
await orbit.waitForText("Dashboard", { timeout: 10000, interval: 200 });
// Avoid: arbitrary sleep, slow on fast machines, flaky on slow ones
await orbit.wait(2000);

orbit.wait(ms) exists for the rare cases where nothing observable changes (an animation you must let finish, a debounce with no signal). Reach for it last, and leave a comment saying why.

When one locator matches many elements, orbit.all() (alias: orbit.elements()) returns an array of reusable locator snapshots:

const products = await orbit.all(orbit.css(".product-title"));
for (const product of products) {
const name = await orbit.text(product);
if (name.includes("iPhone")) {
await orbit.click(product);
break;
}
}

Iterate, read, and act on a collection.

Each item carries snapshot details you can inspect directly: tag, text, visible, and attributes. The items support the usual actions: click, hover, doubleClick, rightClick, type, exists, waitFor, and the three text readers.

while (await orbit.exists(orbit.css(".delete"), { timeout: 0 })) {
const deleteButtons = await orbit.all(orbit.css(".delete"));
await orbit.click(deleteButtons[0]);
}

Safe pattern for lists that change as you click.

const page = await orbit.pageState();
expect(page.title).toContain("Dashboard");
expect(page.url).toContain("/dashboard");
// Run code inside the page when you need to
const heading = await orbit.evaluate(() => document.title);
await orbit.evaluate((text) => console.log(text), "hello");

evaluate() is the escape hatch into the page’s own JavaScript. It is great for test setup (stopping an animation clock, reading app state) but resist using it to click or type, that bypasses the user-level behavior your test is supposed to prove.

How do I assert that something disappeared?

Section titled “How do I assert that something disappeared?”

Combine exists with a zero timeout: expect(await orbit.exists(".spinner", { timeout: 0 })).toBe(false), or wait for it to go with a waitFor on the state that replaces it.

Can I type into a field without clearing it first?

Section titled “Can I type into a field without clearing it first?”

type() types into the resolved field. If the field may hold old text, click it and clear it explicitly as part of the flow your user would perform.

Why does my text assertion fail when I can see the text?

Section titled “Why does my text assertion fail when I can see the text?”

Usually whitespace or hidden duplicates. Read the value back with visibleText() and log it; the readers normalize whitespace, so compare against the normalized form.

  • Locators — Target elements by visible text first, then by role, test ID, CSS, or XPath when needed, and which selectors to avoid.
  • Frames & Shadow DOM — Scope tests into iframes and open or closed shadow roots with orbit.frame() and orbit.shadow(), including nested paths.
  • Alerts & Windows — Handle alert, confirm, and prompt dialogs, notification permissions, and multi-window flows with waitForWindow.
  • Test Basics — How to structure readable end-to-end tests: arrange-act-assert, the orbit object, per-test options, and strong assertions.