Layout checks

Check that controls stay apart, text stays readable and a page fits its viewport.

Use layout checks to keep controls apart, text readable and the page free of horizontal scrolling. They measure a specific layout rule, so you can test a bug fix without keeping a screenshot baseline.

Choose a viewport Link to Choose a viewport

Reproduce a layout problem at the width where you saw it. Set the target's viewport in your config so later runs measure the same layout.

retest.config.ts
import { chrome, defineConfig } from '@rehearsal-labs/retest'export default defineConfig({  apps: {    web: chrome({      baseUrl: 'http://127.0.0.1:4173',      viewport: { width: 390, height: 844 },    }),  },})

This gives Chrome a narrow desktop viewport. It reproduces that width for every run, but does not emulate a phone or use a native mobile app.

Check the saved task layout Link to Check the saved task layout

Each matcher names a problem and passes when it finds that problem. Use .not to write a test that fails while the bug exists and passes after you fix it.

tests/tasks.retest.ts
import { expect, test } from '@rehearsal-labs/retest'test('keeps the saved task readable', async ({ page }) => {  await page.goto('/')  await page.getByTestId('task-title').fill('Release checklist')  await page.getByTestId('save-task').click()  await expect(page.getByTestId('saved-task')).toHaveText('Release checklist')  await expect(page.getByTestId('task-title')).not.toOverlap(    page.getByTestId('save-task'),  )  await expect(page.getByTestId('saved-task')).not.toOverflowViewport()  await expect(page.getByTestId('saved-task')).not.toHaveClippedText()  await expect(page).not.toScrollHorizontally()})

The first check keeps the title field and Save button apart. The next two check the saved title's right edge and its text; the last checks horizontal scrolling. Each retries its measurements until it passes or the assertion budget ends, without clicking Save again.

Understand the measurements Link to Understand the measurements

Measurements use CSS pixels and small tolerances to avoid counting rounding as a layout error. Choose the matcher that describes the problem you want to prevent.

MatcherProblem it detects
toOverlap(other)Two visible boxes share more than 4 pixels both across and down.
toOverflowViewport()An element's visible box ends more than 1 pixel past the viewport's right edge.
toHaveClippedText()A container with hidden or clipped overflow cuts off more than 4 pixels of text.
toScrollHorizontally()The document extends more than 1 pixel past the available width, without hiding its horizontal overflow.

toOverlap() needs two separate elements on the same page. An ancestor and its descendant cannot establish either result. A control contained inside a field, such as a clear button, does not count as an overlap.

Clipped text includes words in the matched element and its first 200 descendants. The check ignores intentional ellipses, line clamps and containers that scroll. An element with no words cannot pass either form of the text check.

Read a failure Link to Read a failure

A failed check names the elements, the measured problem and the viewport width. For example, an overflow failure says how many pixels the element extends past the right edge. The assertion event also keeps the measurements for later inspection.

Every element must have exactly one match and be shown. A missing, hidden or ambiguous match cannot prove that a layout problem is absent, so .not does not make those checks pass. Refine the locator or bring the element into its visible state first.

Scope and platform support Link to Scope and platform support

Layout checks measure the elements you name; they do not scan the whole page for problems. The overflow matcher checks the right edge only, so it does not prove that an element fits every edge of the viewport.

The matchers work on Chromium-family browser pages. Firefox, WebKit and native apps report unsupported. For broader visual changes, use Screenshot comparisons.

Next steps Link to Next steps