Skip to main content

The SDK

What your tests cover

Telling the report which criteria your own tests already check, and pointing at the moments only your suite reaches.

Telling the report what your own tests already cover

Some success criteria no automated engine evaluates. Reflow at 320px, focus not being obscured by a sticky header, a keyboard trap, whether the navigation is consistent between pages — these are checked by driving the page, and a suite that has grown up around a real product is usually checking several of them already. Until you say so, the conformance report has no way to know: your spec arrives as a pass or a fail with no criterion attached to it.

So say so:

ts
import { setsquare } from '@setsquare/review-sdk';

test('no horizontal scrolling at 320px', async ({ page }) => {
  setsquare.covers('1.4.10');

  await page.setViewportSize({ width: 320, height: 800 });
  await page.goto('/pricing');
  expect(await hasHorizontalOverflow(page)).toBe(false);
});

That criterion now appears in the report as covered by your own test, with your test named next to it.

It is recorded as your claim, not as our finding, and the report says so everywhere it appears. We do not check that a test declaring 1.4.10 tests reflow — there is no way to — so a declaration is never merged into the state that means every automated rule passed. It is its own state, worded differently, with its own glyph in the grid. That is the point: the declaration is exactly as strong as the test behind it, and the report never pretends otherwise.

Three details worth knowing:

  • A declaring test that fails is reported as your own test for this criterion did not pass, and it stops the level reading as clean. It does not become a detected failure: we did not observe it, and a red test can be red for a reason that has nothing to do with the criterion.
  • A declaring test that is skipped is reported as such, rather than folded into "no automated check exists" — a check that exists and did not run is a different problem.
  • An id that is not a WCAG 2.2 success criterion throws, immediately, in your test. This is the one thing in this package that does: everywhere else a problem warns and carries on, because our evidence-gathering has no standing to fail your build. A typo here is different — the alternative is dropping your declaration silently, which would leave you believing you have coverage you do not have.

When pointing is enough for us to measure it

Some criteria are out of reach only because we do not know something you do — not because the rest of them is a judgement. 2.2.5 Re-authenticating is the first: the criterion asks that a user "can continue the activity without loss of data after re-authenticating", and the only part nobody but your suite knows is when the session expired. Once you point at that moment, what is left is arithmetic.

ts
await page.goto('/checkout');
await page.fill('#address', '12 Example Street');

await setsquare.acrossReauthentication(page, async () => {
  await page.context().clearCookies(); // however your application ends a session
  await signBackIn(page);
});

We read the form on both sides of your callback and report which fields came back. That is our finding, not your claim — it lands in the report the way any other measurement does, with a count and the fields named.

Three things it will not do:

  • It never fails the criterion. A field that came back empty is a question. A CSRF token and a one-time code are supposed to be discarded, and G181 — one of the criterion's own sufficient techniques — carries the data through a re-authorization page as hidden fields, which we deliberately do not read.
  • Nothing you typed leaves the page. The values are hashed in the browser with a salt made for that one call, so what we hold is a token we can only compare against another token. What reaches the report is a selector and a count.
  • A form is not an activity. State in a store, a draft on the server and the step of a wizard are all part of continuing what somebody was doing, and none of them is visible to this. The report says so next to the criterion.

3.3.4 and 3.3.6 work the same way, for the same reason. Both are met by any one of three escapes, and only the third leaves anything in a page: "a mechanism is available for reviewing, confirming, and correcting information before finalizing the submission".

ts
await setsquare.acrossSubmission(page, { consequential: true }, async () => {
  await page.click('#review-order'); // drive it to the step before it completes
});

We compare what was entered against what the page presents back, and report whether all three verbs were there. consequential: true is the part only you know — a rule can see a form and cannot see that the form buys an aeroplane ticket — and it is what adds 3.3.4. Without it the call still reports 3.3.6, which applies to every page that requires a submission.

It is never a failure. Reversible (the submission can be undone) and Checked (invalid data is rejected with a chance to correct it) each meet the criterion on their own, and neither leaves anything in a document to find. And the number we report is the submissions your tests drove — never all of them, because we will not submit every form on your application to find out.