Skeleton Conventions

The naming, signature, and XPath-style rules the framework enforces on every scaffolded App — so a Custom Step, a Self-Healing writeback, or a hand-edit all produce byte-consistent code.

← Back to overview · 🇩🇪 Deutsch · ← Writing Your First TestCase


What these conventions cover

Structure — naming, function signature, import order, i18n wrapping — follows 6 fixed rules, checked automatically on every new file. Semantics — which Control, which label, which XPath fragment — stays your decision; the rules below only constrain the shape the code takes, never what it does.


The 6 rules

Rule Kind What it checks Severity
R1 — i18n i18n Every Core.i18n.t('KEY', ...) and every descriptionI18n.key: 'KEY' has an en entry in its sibling .i18n.json catalog; every locale variant has identical placeholders Fatal
R2 — Naming Steps Every exported TS_* in a step file matches TS_<Type>_<Element>_<Action> (e.g. TS_Main_Button_Click) Fatal
R3 — Signature Steps Every Core.defineTestStep’s run callback has pageLogName: string, _?sectionName: string as its first two parameters (TS_Main/TS_Dialog/TS_Message only) Fatal
R4 — XPath Style Controls Skeleton Controls forbid @id, [@data-testid], [@data-cy] — the framework style is structural (text/role/label) Fatal
R5 — Sibling Catalog i18n Every TS_*.ts with at least one defineTestStep has a sibling TS_*.i18n.json Fatal
R6 — Import Order Steps Imports appear in canonical order: Core → Controls* (alphabetical) → other Warning

Check your files automatically

  • Pre-commit hook. After npm install inside pm/, simple-git-hooks installs a .git/hooks/pre-commit hook that validates the Skeleton files touched by the current commit.
  • CI. A Validate Skeleton Conventions step runs on every pull request and push.
  • CLI, on demand. From inside pm/: node node_modules/@meintest/cc-testframework-templates/bin/validate-conventions.js <root> runs the full rule set against a directory tree — manually, or wired into your own CI. Exit codes: 0 everything clean, 1 at least one fatal violation, 2 warnings only.
  • Machine-readable output. The --json flag emits structured findings for a test-management tool or other external consumer instead of the human-readable text report.

Generated code — a Self-Healing writeback, or a step the Custom-Steps Authoring Agent produces — is checked against these same rules before it’s ever written to your source file, so it conforms from the moment it lands. See Self-Healing Locators and Custom Steps for what each of those write paths does.


What to do when validation fails

R1 — i18n

// Wrong — key 'TS_Main_Login_Click' has no en entry in the sibling catalog
Core.i18n.t('TS_Main_Login_Click', { user: 'alice' });

Fix: add the entry to the sibling .i18n.json catalog:

{
  "TS_Main_Login_Click": { "en": "click Login for ${user}", "de": "..." }
}

R2 — Naming

// Wrong
export const clickLoginButton = ...

// Correct
export const TS_Main_Button_Click = Core.defineTestStep('MyApp', { ... });

R3 — Signature

// Wrong — run callback is missing pageLogName
Core.defineTestStep('MyApp', {
    descriptionI18n: { ... },
    run: (label: string) => Controls.click(label),
});

// Correct
Core.defineTestStep('MyApp', {
    descriptionI18n: { ... },
    run: (_pageLogName: string, _sectionName: string, label: string) => Controls.click(label),
});

R4 — XPath Style

// Wrong — Skeleton style is structural, not id-based
Core.xpath`.//*[@id='login-btn']`

// Correct
Core.xpath`.//button[.='${label}']`

R5 — Sibling Catalog

TS_Main.ts with at least one defineTestStep but no TS_Main.i18n.json next to it fails as Fatal. Create the sibling catalog file, even if it starts out empty ({}).

R6 — Import Order

// Wrong — Controls import appears before Core
import * as ControlsButton from '../1_Controls/Button';
import * as Core from '@Core';

// Correct
import * as Core from '@Core';
import * as ControlsButton from '../1_Controls/Button';

Know which of your files are checked

R2, R3, and R4 only apply when the validator’s root points at the Skeleton itself (packages/templates/templates). For your own Apps under pm/2_Apps/, only R1 and R5 are active — R2, R3, and R4 are skipped with an info-level log line, since those Apps grew before these conventions existed. Turn full enforcement on for your own Apps with strictConventions — see the next section.


Enforce all 6 rules on your own Apps (strictConventions)

By default, R2 (Naming), R3 (Signature), and R4 (XPath Style) apply only to the Skeleton itself, so Apps that grew before these conventions existed, or that already established their own naming or XPath style, keep working unchanged.

Opt in to the same guarantees on your own Apps under 2_Apps/ when you want a Self-Healing writeback, a hand-edit, or any external tool to stop drifting away from your naming, signature, and XPath style over time. Three ways to activate it, checked in this order — the first one found wins:

  1. CLI flag. Pass --strict when invoking validate-conventions.js directly, e.g. from your own pre-commit configuration.
  2. Environment variable. Set STRICT_CONVENTIONS=true — typically in your CI configuration, so every pipeline run enforces it without touching a project file.
  3. GlobalConfig.ts. Add to 2_Apps/1_Global/GlobalConfig.ts:
// In 2_Apps/1_Global/GlobalConfig.ts
export const strictConventions = true;

This is the persistent, repo-committed option — once set, every commit and every CI run enforces it, with no flag or env-var needed elsewhere. A newly scaffolded App ships this line commented out in its GlobalConfig.ts; uncomment it when you’re ready.

If none of the three is set, the framework falls back to the default described above — R2, R3, and R4 stay Skeleton-only; R1 and R5 stay active everywhere regardless.

What changes when it’s on

R2, R3, and R4 now run against every file under 2_Apps/**, not just the Skeleton. In practice, this catches:

  • Self-Healing writeback drift. A healed locator comes from a Vision call and can occasionally propose an @id- or [data-testid]-style XPath even though the rest of your Control follows the structural style. See Self-Healing Locators for how that interacts with strictConventions.
  • Hand-edit drift. A teammate renaming a step or adjusting a signature by hand is checked the same way a Skeleton file already is.

What this does not catch

strictConventions runs at commit-time and in CI — it validates files that already exist on disk. It does not catch Authoring-Agent-generated Custom-Step code before that code is written to your source file in the first place; that’s a separate, earlier checkpoint described in How generated code is verified.


Where to go next


📧 Questions? Contact: jens.szelag@itsbusiness.ch

itsbusiness AG · Bern · Switzerland