Skip to main content

Specs: the English description of a test

A spec is a plain-English markdown file that describes one test scenario. It lives in tests/specs/ and is the source of truth for everything the AI generates. If you want a test to do something different, you update the spec — not the generated TypeScript.

What a spec file looks like​

Every spec has two parts: a YAML header (called frontmatter) and a body with named sections.

The frontmatter​

The frontmatter sits between the --- fences at the very top of the file.

---
id: PROJECT-TEAM-ADD-KEY-MEMBER-001
feature: project
title: 'Case: Add Account Manager key member'
priority: high
tags: [happy-path, project-team]
fixture: projectTeamPage
data:
- team.account_manager_smith
---
FieldWhat it means
idUnique identifier used by the generator and CI to track this spec.
featureThe PACE feature area this spec belongs to (project, estimates, clients, …).
titleHuman-readable name shown in test reports.
priorityHow critical the scenario is — used to decide which tests run in a short smoke suite.
fixtureThe Playwright fixture that sets up the browser state (logs in, navigates to the right page).
dataOne or more dotted keys into tests/data/*.jsonc — the real values the test will use.

The body sections​

After the frontmatter the spec has three sections:

  • ## Background — A sentence or two explaining what the test is proving and any setup assumptions. Written for a human reader, not the test runner.
  • ## Steps — A numbered list of actions. Each step has three parts (see below).
  • ## Expected — What the tester should observe at the end of a successful run.

Inside a step​

Each numbered step has three pieces:

3. Click "Add new member" and capture the new row index
- intent: "Append a fresh row so the new key member's role + person can be set."
- method: `tp.clickAddNewMember()` then `(await grid.getRowCount()) - 1`
PartPurpose
proseThe human description — what a tester would say out loud while doing this manually.
intentThe why behind the step, written in plain English. The AI uses this to write assertions.
methodThe page-object or helper calls the Generator will translate into TypeScript.

The method: field is essentially a recipe written in pseudo-code using the page-object API. You do not need to know TypeScript to read it — it is meant to be self-explanatory.

A real excerpt​

Here are steps 3–6 from tests/specs/project/team/add-key-member.md, the spec that tests adding an Account Manager to a project's Key Members grid:

3. Click "Add new member" and capture the new row index
- intent: "Append a fresh row so the new key member's role + person can be set."
- method: `tp.clickAddNewMember()` then `(await grid.getRowCount()) - 1`
4. Pick the role in the new row's role dropdown
- intent: "Assign the Account Manager role — driven by data so the spec can be
re-run for other roles by swapping data refs."
- method: `grid.selectCellDropdownOption('role_id', newRowIndex, member.role_id)`
5. Pick the person in the new row's person dropdown
- intent: "Pick the specific named person for the role."
- method: `grid.selectCellDropdownOption('person_id', newRowIndex, member.person_id)`
6. Save and wait for the success toast
- intent: "Persist the change and assert the server accepted it via the toast —
a single round-trip validation."
- method: `tp.wait.expectToastAfterAction('success', () => tp.save())`

Notice that member.role_id and member.person_id are data references — not hard-coded strings. The real values live in tests/data/team.jsonc and flow in via the data: frontmatter key. See Test data for details.

Requesting a new page-object method​

Sometimes a spec needs a page-object method that does not exist yet. You signal this with a [NEW: ClassName.methodName()] annotation in the method: field:

2. Open the project settings panel
- intent: "Navigate to the settings tab so we can edit the project name."
- method: `[NEW: ProjectPage.openSettingsPanel()]`

When the Generator sees [NEW: ...] it reads the application source to learn the correct selectors, writes the method, and adds it to the page object before producing the test file.

Specs vs. generated test files​

The spec (tests/specs/…/*.md) is the thing you own and maintain. The generated test file (tests/e2e/…/*.spec.ts) is produced by the Generator agent and should not be hand-edited — if you edit it directly, those changes will be lost the next time the Generator runs. When you want to change a test's behaviour, update the spec and regenerate.