@testspectra/skills 1.1.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE.md +48 -0
  2. package/README.md +78 -0
  3. package/bin/spectra-skills.js +7 -0
  4. package/dist/commands/add.d.ts +1 -0
  5. package/dist/commands/add.js +44 -0
  6. package/dist/commands/init.d.ts +1 -0
  7. package/dist/commands/init.js +54 -0
  8. package/dist/commands/list.d.ts +1 -0
  9. package/dist/commands/list.js +22 -0
  10. package/dist/commands/remove.d.ts +1 -0
  11. package/dist/commands/remove.js +26 -0
  12. package/dist/commands/update.d.ts +1 -0
  13. package/dist/commands/update.js +30 -0
  14. package/dist/detector.d.ts +35 -0
  15. package/dist/detector.js +129 -0
  16. package/dist/index.d.ts +8 -0
  17. package/dist/index.js +119 -0
  18. package/dist/registry.d.ts +8 -0
  19. package/dist/registry.js +48 -0
  20. package/dist/skills/fixtures-data/SKILL.md +109 -0
  21. package/dist/skills/lifecycle-hooks/SKILL.md +114 -0
  22. package/dist/skills/matchers-and-assertions/SKILL.md +123 -0
  23. package/dist/skills/network-interception/SKILL.md +115 -0
  24. package/dist/skills/page-objects-and-selectors/SKILL.md +107 -0
  25. package/dist/skills/shared-steps-and-actions/SKILL.md +184 -0
  26. package/dist/skills/spec-and-suite-authoring/SKILL.md +132 -0
  27. package/dist/skills/workspace-structure/SKILL.md +181 -0
  28. package/package.json +59 -0
  29. package/skills/fixtures-data/SKILL.md +109 -0
  30. package/skills/lifecycle-hooks/SKILL.md +114 -0
  31. package/skills/matchers-and-assertions/SKILL.md +123 -0
  32. package/skills/network-interception/SKILL.md +115 -0
  33. package/skills/page-objects-and-selectors/SKILL.md +107 -0
  34. package/skills/shared-steps-and-actions/SKILL.md +184 -0
  35. package/skills/spec-and-suite-authoring/SKILL.md +132 -0
  36. package/skills/workspace-structure/SKILL.md +181 -0
@@ -0,0 +1,184 @@
1
+ ---
2
+ name: shared-steps-and-actions
3
+ description: The difference between TestSpectra Shared Steps (Step.*, high-level business workflows, documented in spec.md via @step) and Spectra Actions (support/actions, low-level technical utilities) — directory layout, the mandatory anonymous async default export convention, and ambient type generation. Use whenever extracting reusable logic out of a test script.
4
+ ---
5
+
6
+ # Skill: Shared Steps vs. Custom Actions
7
+
8
+ Use this skill when you're about to extract repeated logic (e.g. login, checkout) out of test
9
+ scripts, or when deciding whether new reusable logic belongs under `support/steps/` or
10
+ `support/actions/`.
11
+
12
+ ---
13
+
14
+ ## 1. Which One Do I Need?
15
+
16
+ | Attribute | Shared Steps (`Step.*`) | Custom Actions (`Spectra.*` / on-element helpers) |
17
+ | :---------------- | :--------------------------------------------- | :---------------------------------------------------------------------------- |
18
+ | Abstraction level | High-level business workflow (login, checkout) | Low-level technical utility |
19
+ | Directory | `support/steps/<stepName>/` | `support/actions/<actionName>/` |
20
+ | Spec mapping | Documented as `@step:<name>` in `spec.md` | Just called inline, not listed in spec steps |
21
+ | Metadata file | `step.md` (YAML frontmatter + description) | None — implementation file only |
22
+ | Files | `step.md` + `web.step.ts` [+ `mobile.step.ts`] | `web.action.ts` [+ `mobile.action.ts`] |
23
+ | Invocation | `await Step.loginAsAdmin(params)` | Called as a helper bound to an element/page, e.g. inside a Page Object method |
24
+
25
+ Rule of thumb: if it's a multi-step _business_ flow a human would describe in one sentence
26
+ ("log in as admin"), it's a **Step**. If it's a small technical helper reused across Page Objects
27
+ (a resilient click retry, filling a pair of fields), it's an **Action**.
28
+
29
+ ---
30
+
31
+ ## 2. Directory Layout
32
+
33
+ ```
34
+ support/
35
+ ├── steps/
36
+ │ └── loginAsAdmin/
37
+ │ ├── step.md # Metadata, docs, parameter types
38
+ │ ├── web.step.ts
39
+ │ └── mobile.step.ts # optional
40
+ └── actions/
41
+ └── fillCredentials/
42
+ ├── web.action.ts
43
+ └── mobile.action.ts
44
+ ```
45
+
46
+ Both use **camelCase** directory/function names (`loginAsAdmin`, `fillCredentials`,
47
+ `applyDiscount`, `verifyOtp`) — never kebab-case or snake_case.
48
+
49
+ ---
50
+
51
+ ## 3. `step.md` Metadata
52
+
53
+ ```markdown
54
+ ---
55
+ id: step-login-as-admin
56
+ name: loginAsAdmin
57
+ description: Authenticates as an administrator and asserts landing dashboard
58
+ platform:
59
+ - web
60
+ - mobile
61
+ tags:
62
+ - auth
63
+ - admin
64
+ parameters:
65
+ - name: email
66
+ type: string
67
+ required: false
68
+ description: Admin email address (defaults to Fixture.users.admin.email)
69
+ - name: password
70
+ type: string
71
+ required: false
72
+ description: Admin password (defaults to Fixture.users.admin.password)
73
+ ---
74
+
75
+ # Login as Admin Step
76
+
77
+ ## Purpose
78
+
79
+ Provides a standard, hardened administrative login sequence for web and mobile platforms.
80
+
81
+ ## Prerequisites
82
+
83
+ - User fixture file exists at `fixtures/users.json`.
84
+ - Browser is navigated to the base URL or login route.
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 4. Implementation: Anonymous Async Default Export (Mandatory)
90
+
91
+ Every `*.step.ts` and `*.action.ts` file exports **one anonymous async function as its default
92
+ export** — no named exports, no `test()`/`it()` blocks. This is enforced by the linter
93
+ (`testspectra/require-anonymous-default-export`).
94
+
95
+ ```typescript
96
+ // support/steps/loginAsAdmin/web.step.ts
97
+ export default async function (params?: { email?: string; password?: string }) {
98
+ const email = params?.email ?? Fixture.users.admin.email;
99
+ const password = params?.password ?? Fixture.users.admin.password;
100
+
101
+ await Spectra.navigate('/auth/login');
102
+ await LoginPage.emailInput.type(email, { clearFirst: true });
103
+ await LoginPage.passwordInput.type(password);
104
+ await LoginPage.submitButton.click();
105
+
106
+ await DashboardPage.header.shouldBeVisible();
107
+ }
108
+ ```
109
+
110
+ Custom Actions follow the same shape and are commonly written with a `this` receiver so they can
111
+ be attached/bound as element/page helpers:
112
+
113
+ ```typescript
114
+ // support/actions/fillCredentials/web.action.ts
115
+ export default async function (this: any, email: string, token: string) {
116
+ await this.get('#demo-email-input-pg').type(email);
117
+ await this.get('#demo-token-input-pg').type(token);
118
+ }
119
+ ```
120
+
121
+ ```typescript
122
+ // support/actions/fillCredentials/mobile.action.ts
123
+ export default async function (this: any, email: string, token: string) {
124
+ await this.get('~pg-email-input').type(email);
125
+ await this.get('~pg-token-input').type(token);
126
+ }
127
+ ```
128
+
129
+ Zero-import applies here too: never manually `import` a Page Object, `Fixture`, or `Spectra` — see
130
+ the `workspace-structure` skill.
131
+
132
+ ---
133
+
134
+ ## 5. Type Generation & Invocation
135
+
136
+ The `TypeGenerator` scans `support/steps/` and emits the `Step` ambient namespace automatically:
137
+
138
+ ```typescript
139
+ declare global {
140
+ namespace Step {
141
+ function loginAsAdmin(params?: { email?: string; password?: string }): Promise<void>;
142
+ }
143
+ }
144
+ ```
145
+
146
+ ### In `spec.md` (documents the step as part of the human-readable flow):
147
+
148
+ ```markdown
149
+ ## Test Steps
150
+
151
+ 1. @step:loginAsAdmin
152
+ 2. Navigate to user settings page
153
+ 3. Update profile avatar
154
+ ```
155
+
156
+ ### In `web.test.ts` (invokes it with zero manual imports):
157
+
158
+ ```typescript
159
+ it('should update admin profile avatar', async () => {
160
+ await Step.loginAsAdmin();
161
+
162
+ await SettingsPage.openProfile();
163
+ await SettingsPage.avatarInput.type('avatar.png');
164
+ await SettingsPage.successToast.shouldBeVisible();
165
+ });
166
+ ```
167
+
168
+ Every `@step:<name>` in `spec.md` must have a matching `Step.<name>()` call in the paired test
169
+ script, or `spectra lint` reports `testspectra/missing-step-call`. See the
170
+ `spec-and-suite-authoring` skill for the full linter rule matrix.
171
+
172
+ ---
173
+
174
+ ## 6. Renaming a Step or Action
175
+
176
+ Never rename a step/action folder by hand. Use:
177
+
178
+ ```
179
+ spectra refactor step loginAsAdmin authenticateAdmin
180
+ ```
181
+
182
+ This atomically: renames `support/steps/loginAsAdmin/` → `support/steps/authenticateAdmin/`,
183
+ updates `name:` in `step.md`, rewrites every `@step:loginAsAdmin` in every `spec.md`, rewrites
184
+ every `Step.loginAsAdmin()` call site, and regenerates `.testspectra/types/steps.d.ts`.
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: spec-and-suite-authoring
3
+ description: How to write suite.md, spec.md, and the paired *.test.ts execution script for a TestSpectra test case — frontmatter schema, the @step directive convention, and every spec-schema-linter rule that must pass (single it(), no describe/test, zero-import, title parity). Use whenever creating or editing a test case.
4
+ ---
5
+
6
+ # Skill: Spec & Suite Authoring (`spec.md`, `suite.md`, `*.test.ts`)
7
+
8
+ Use this skill whenever you create a new test case, add a new suite, or edit an existing
9
+ `spec.md` / `*.test.ts` pair. TestSpectra treats the Markdown spec as the human-readable source of
10
+ truth and the TypeScript file as its execution — the CLI linter (`spectra lint`) enforces that the
11
+ two never drift apart.
12
+
13
+ ---
14
+
15
+ ## 1. Directory Convention
16
+
17
+ ```
18
+ specs/<SuiteName>/suite.md
19
+ specs/<SuiteName>/hooks/{before,beforeEach,afterEach,after}/web.hook.ts
20
+ specs/<SuiteName>/TC-<NNNN>-<kebab-slug>/spec.md
21
+ specs/<SuiteName>/TC-<NNNN>-<kebab-slug>/web.test.ts # + android/ios/mobile/common variants
22
+ ```
23
+
24
+ `SuiteName` is a directory (no `describe()` block ever exists in code — the suite boundary is
25
+ purely the folder). The test case id (`TC-0001-valid-login`) is both the directory name and the
26
+ `id` in `spec.md`'s frontmatter, and must be unique across the entire workspace
27
+ (`testspectra/duplicate-spec-id`).
28
+
29
+ ---
30
+
31
+ ## 2. `suite.md` Frontmatter
32
+
33
+ ```markdown
34
+ ---
35
+ name: Untitled Suite
36
+ id: suite-element-matchers
37
+ description: Element visibility, existence, form states and attributes
38
+ executionOrder: 1.0
39
+ parallel: true
40
+ ---
41
+
42
+ # Suite: ElementMatchers
43
+ ```
44
+
45
+ ---
46
+
47
+ ## 3. `spec.md` Frontmatter & Body
48
+
49
+ ```markdown
50
+ ---
51
+ id: TC-0003-visibility-and-dom
52
+ title: Verify element visibility and existence matchers
53
+ priority: High
54
+ caseType: Positive
55
+ status: ready-for-automation
56
+ coverage:
57
+ web: automated
58
+ mobile: automated
59
+ ---
60
+
61
+ # Verify element visibility and existence matchers
62
+
63
+ ## Test Steps
64
+
65
+ 1. Open visibility section in matchers page
66
+ 2. Assert visible element has be.visible state
67
+ 3. Assert existing element exists in DOM
68
+ ```
69
+
70
+ Required frontmatter: `id`, `title`, `priority`, `caseType`, `status` — missing any of these, or
71
+ missing the `# <Title>` / `## Test Steps` headings, triggers `testspectra/missing-frontmatter`.
72
+ Invalid enum values (an unrecognized `priority`, `caseType`, or `status`) trigger
73
+ `testspectra/invalid-frontmatter-enum`.
74
+
75
+ If the test case invokes a shared step (see the `shared-steps-and-actions` skill), reference it in
76
+ the `## Test Steps` list as `@step:<stepName>` — the linter cross-checks this against
77
+ `Step.<stepName>()` calls in the paired `*.test.ts`.
78
+
79
+ ---
80
+
81
+ ## 4. The Paired Test Script (`web.test.ts`)
82
+
83
+ ```typescript
84
+ it('Verify element visibility and existence matchers', async () => {
85
+ await MatchersPage.open('visibility');
86
+
87
+ await MatchersPage.visibleElement.shouldBeVisible();
88
+ await MatchersPage.hiddenElement.shouldNotBeVisible();
89
+
90
+ await MatchersPage.existingElement.shouldExist();
91
+ await Spectra.get('#demo-non-existent-el').shouldNotExist();
92
+ });
93
+ ```
94
+
95
+ ### Hard rules (each is a `spectra lint` error unless noted):
96
+
97
+ 1. **Exactly one `it(...)` block, nothing else at the top level.** Zero or multiple `it()` blocks
98
+ → `testspectra/single-it-required`.
99
+ 2. **Never `test(...)`.** Only `it(...)` is allowed → `testspectra/no-test-block`.
100
+ 3. **Never `describe(...)`.** Suite grouping is the directory, not code →
101
+ `testspectra/no-describe-block`.
102
+ 4. **Zero manual `import`s.** See the `workspace-structure` skill →
103
+ `testspectra/no-manual-import`.
104
+ 5. **`it()`'s title should read the same as `spec.md`'s `title`** (case-insensitive semantic
105
+ match). A mismatch is a warning, not an error → `testspectra/title-mismatch`.
106
+ 6. **Every `@step:<name>` in `spec.md` must have a matching `Step.<name>()` call** in the test
107
+ script → `testspectra/missing-step-call` (error) if absent, and conversely a `Step.<name>()`
108
+ call not documented with `@step:<name>` in `spec.md` is
109
+ `testspectra/undocumented-step` (warning).
110
+
111
+ ### Platform variants
112
+
113
+ A test case directory may contain any combination of `web.test.ts`, `android.test.ts`,
114
+ `ios.test.ts`, `mobile.test.ts`, `common.test.ts` — each is linted and can be run independently.
115
+ Reuse a shared step for the parts of the flow that are identical across platforms rather than
116
+ duplicating the `it()` body per platform.
117
+
118
+ ---
119
+
120
+ ## 5. Running the Linter
121
+
122
+ - `spectra lint` — scan the whole workspace, human-readable output.
123
+ - `spectra lint --strict` — treat warnings as errors, exit code `1` on any diagnostic (use this in
124
+ CI).
125
+ - `spectra lint --json` — machine-readable diagnostics (what an AI agent should parse to
126
+ self-correct after generating a spec).
127
+ - `spectra lint <path>` — scan a single suite or test case folder.
128
+
129
+ Exit codes: `0` valid, `1` violations found, `2` fatal (malformed YAML/JSON).
130
+
131
+ After authoring or editing a `spec.md`/`*.test.ts` pair, run `spectra lint <path-to-that-case>`
132
+ before considering the task done.
@@ -0,0 +1,181 @@
1
+ ---
2
+ name: workspace-structure
3
+ description: TestSpectra workspace layout, zero-import ambient type architecture, platform file suffixes (web/android/ios/mobile/common), spectra.config.ts, and the core spectra CLI commands. Use before scaffolding any new TestSpectra project or file so it lands in the right directory with the right suffix.
4
+ ---
5
+
6
+ # Skill: TestSpectra Workspace Structure & Zero-Import Architecture
7
+
8
+ Use this skill whenever you scaffold a new TestSpectra workspace, add a new file to an existing
9
+ one, or need to decide where a Page Object / Step / Action / Hook / Fixture belongs.
10
+
11
+ ---
12
+
13
+ ## 1. Core Philosophy: Git-First, Spec-as-Code
14
+
15
+ Every test case, shared step, Page Object, fixture, and config file is a plain TypeScript or
16
+ Markdown file tracked in git — there is no proprietary binary project format. TestSpectra supports
17
+ two workspace paradigms:
18
+
19
+ 1. **Default Project Mode** (`spectra init`, single-root repo) — one app, one `spectra.config.ts`.
20
+ 2. **Monorepo / Nx Project Mode** (`spectra init --template nx`) — multiple `packages/*` test
21
+ projects sharing a library under `shared/testing` (or a custom path), wired into
22
+ `pnpm-workspace.yaml`.
23
+
24
+ Never guess which mode a repo uses — check for `nx.json` / `pnpm-workspace.yaml` with a
25
+ `packages:` list first.
26
+
27
+ ---
28
+
29
+ ## 2. Default Workspace Directory Layout
30
+
31
+ ```
32
+ my-test-project/
33
+ ├── .testspectra/ # Auto-managed. NEVER hand-edit these files.
34
+ │ ├── tsconfig/ # web.json, mobile.json, android.json, ios.json, common.json
35
+ │ ├── types/ # web.d.ts, mobile.d.ts, android.d.ts, ios.d.ts, common.d.ts,
36
+ │ │ # fixtures.d.ts — ambient globals (Spectra, Step, Fixture, POs)
37
+ │ └── reports/ # report.json, network-resources.json, last-run.json
38
+ │
39
+ ├── specs/ # Test suites & test cases (Spec-as-Code)
40
+ │ └── <SuiteName>/
41
+ │ ├── suite.md # Suite metadata (id, name, executionOrder, parallel)
42
+ │ ├── hooks/ # Suite-level lifecycle hooks (before/beforeEach/afterEach/after)
43
+ │ └── TC-<NNNN>-<slug>/ # One directory per test case
44
+ │ ├── spec.md # Frontmatter + "## Test Steps" with @step:<name> directives
45
+ │ ├── web.test.ts # and/or android.test.ts / ios.test.ts / mobile.test.ts / common.test.ts
46
+ │
47
+ ├── page-objects/ # Page Object Model singletons
48
+ │ └── <PageName>/
49
+ │ ├── web.ts
50
+ │ └── mobile.ts # (or android.ts / ios.ts)
51
+ │
52
+ ├── support/
53
+ │ ├── steps/ # High-level reusable business workflows (Step.*)
54
+ │ │ └── <stepName>/
55
+ │ │ ├── step.md
56
+ │ │ ├── web.step.ts
57
+ │ │ └── mobile.step.ts
58
+ │ └── actions/ # Low-level technical utilities (Spectra.<action>())
59
+ │ └── <actionName>/
60
+ │ ├── web.action.ts
61
+ │ └── mobile.action.ts
62
+ │
63
+ ├── fixtures/ # JSON/CSV test data, auto-typed under Fixture.*
64
+ │ └── users.json
65
+ │
66
+ ├── global-hooks/ # Workspace-wide hooks, run once per Global Batch Run only
67
+ │ ├── before/
68
+ │ └── after/
69
+ │
70
+ ├── spectra.config.ts # Single source of truth for execution settings
71
+ ├── tsconfig.json # References ./.testspectra/tsconfig.json — do not add "include"
72
+ └── package.json # Has "postinstall": "spectra sync-types"
73
+ ```
74
+
75
+ For the Nx/monorepo variant, each `packages/<project>/` is its own self-contained workspace
76
+ (`specs/`, `page-objects/`, `spectra.config.ts`, `package.json`), and a shared library
77
+ (default `shared/testing/`) holds cross-project Page Objects/Steps/Actions/Fixtures. **Never** put
78
+ a `specs/` directory or a `spec.md`/`suite.md` file inside the shared library — the linter rejects
79
+ it (`testspectra/no-specs-in-shared-lib`).
80
+
81
+ ---
82
+
83
+ ## 3. Zero-Import Rule (Non-Negotiable)
84
+
85
+ TestSpectra scripts **never** contain a manual `import` statement for framework entities. Page
86
+ Objects, `Step.*`, `Fixture.*`, and the global `Spectra` object are all injected as ambient
87
+ globals via `.testspectra/types/*.d.ts`, which the CLI regenerates automatically (sub-60ms) when
88
+ you add/rename files under `page-objects/`, `support/`, or `fixtures/`.
89
+
90
+ - ❌ `import LoginPage from '../../page-objects/LoginPage';`
91
+ - ✅ Just reference `LoginPage` directly — it resolves globally.
92
+
93
+ Adding an `import` in a `*.test.ts`, `*.step.ts`, `*.action.ts`, `*.hook.ts`, or Page Object file
94
+ triggers linter rule `testspectra/no-manual-import` (error). If a file's types look stale after you
95
+ add a new Page Object/Step/Fixture, run `spectra sync-types` rather than importing manually.
96
+
97
+ ---
98
+
99
+ ## 4. Platform File Suffixes
100
+
101
+ | Suffix | Target | Can access |
102
+ | :------------ | :-------------------------- | :-------------------------------------------- |
103
+ | `*.web.*` | Web (Chrome CDP) | web + common |
104
+ | `*.android.*` | Android (native TCP driver) | android + mobile + common |
105
+ | `*.ios.*` | iOS (XCUITest) | ios + mobile + common |
106
+ | `*.mobile.*` | Shared Android & iOS | mobile + common only (no web, no android/ios) |
107
+ | `*.common.*` | Universal (web + mobile) | common only (strictest isolation) |
108
+
109
+ This applies to test scripts (`web.test.ts`), Page Objects (`web.ts`), steps (`web.step.ts`),
110
+ actions (`web.action.ts`), and hooks (`web.hook.ts`). Pick the narrowest suffix that fits — don't
111
+ write a `mobile.test.ts` for something that is actually web-only.
112
+
113
+ ---
114
+
115
+ ## 5. `spectra.config.ts`
116
+
117
+ ```typescript
118
+ import { defineConfig } from '@testspectra/cli';
119
+
120
+ export default defineConfig({
121
+ webConfig: {
122
+ baseUrl: 'http://localhost:5173',
123
+ maxConcurrentSessions: '1',
124
+ headless: true,
125
+ implicitWait: '5000',
126
+ pageLoadTimeout: '30000',
127
+ scriptTimeout: '30000',
128
+ parallelizationMode: 'testcase', // "testcase" | "suite"
129
+ },
130
+ browsers: [{ id: 'chrome-desktop', type: 'chrome', mobileEmulation: false }],
131
+ androidConfig: {
132
+ driverServer: 'tcp://127.0.0.1:8200',
133
+ appPackage: 'dev.example.app',
134
+ appActivity: 'dev.example.app.MainActivity',
135
+ noReset: false,
136
+ implicitWait: '10000',
137
+ parallelizationMode: 'suite',
138
+ devices: [{ id: 'emulator-5554', name: 'Pixel 8a Emulator', version: '14.0', systemPort: 8200 }],
139
+ },
140
+ iosConfig: {
141
+ appiumServer: 'http://127.0.0.1:4723',
142
+ automationName: 'XCUITest',
143
+ bundleId: '',
144
+ autoAcceptAlerts: true,
145
+ noReset: false,
146
+ implicitWait: '10000',
147
+ parallelizationMode: 'suite',
148
+ devices: [
149
+ { id: 'iphone-15-pro', name: 'iPhone 15 Pro Simulator', version: '17.0', udid: 'auto', wdaLocalPort: 8100 },
150
+ ],
151
+ },
152
+ executionConfig: {
153
+ networkMonitoringEnabled: true,
154
+ fastResponseTime: '200',
155
+ normalResponseTime: '1000',
156
+ monitoredDomains: [],
157
+ environmentVariables: [],
158
+ },
159
+ });
160
+ ```
161
+
162
+ Numeric-looking fields (timeouts, ports, session counts) accept either a `number` or a numeric
163
+ `string` — stay consistent with whatever the rest of the file already uses.
164
+
165
+ ---
166
+
167
+ ## 6. Core `spectra` CLI Commands
168
+
169
+ | Command | Purpose |
170
+ | :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------ |
171
+ | `spectra init [--template nx]` | Scaffold a new workspace |
172
+ | `spectra sync-types` | Regenerate `.testspectra/types` and `.testspectra/tsconfig` (also runs on `postinstall` and file-watch) |
173
+ | `spectra run [path] -t <web\|mobile\|android\|ios>` | Execute tests |
174
+ | `spectra lint [path] [--strict] [--json]` | Validate `spec.md`/`suite.md` schema + code parity (see the `spec-and-suite-authoring` skill) |
175
+ | `spectra doctor` | Preflight dependency/environment health check |
176
+ | `spectra refactor step\|action\|fixture <old> <new>` | Atomically rename across folder, metadata, and all call sites |
177
+ | `spectra watch` | Background file watcher driving `sync-types` |
178
+
179
+ After scaffolding or renaming any file under `page-objects/`, `support/`, or `fixtures/`, assume
180
+ the ambient types are stale until `sync-types` (or the watcher) has run — don't hand-write
181
+ `.testspectra/types/*.d.ts` yourself.
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@testspectra/skills",
3
+ "version": "1.1.0-rc.0",
4
+ "description": "Installer & manager for modular AI agent skills that standardize TestSpectra script authoring (specs, page objects, steps, actions, hooks, fixtures, matchers)",
5
+ "keywords": [
6
+ "agents",
7
+ "ai",
8
+ "claude-code",
9
+ "cli",
10
+ "cursor",
11
+ "kilo",
12
+ "opencode",
13
+ "skills",
14
+ "testspectra",
15
+ "spectra"
16
+ ],
17
+ "homepage": "https://github.com/TestSpectra/testspectra-source",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/TestSpectra/testspectra-source.git",
21
+ "directory": "tools/skills"
22
+ },
23
+ "bin": {
24
+ "spectra-skills": "./bin/spectra-skills.js",
25
+ "testspectra-skills": "./bin/spectra-skills.js"
26
+ },
27
+ "main": "dist/index.js",
28
+ "types": "dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./package.json": "./package.json"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "bin",
40
+ "skills",
41
+ "README.md",
42
+ "LICENSE.md"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsc && node scripts/copy-skills.js",
46
+ "watch": "tsc -w",
47
+ "typecheck": "tsc --noEmit",
48
+ "prepublishOnly": "npm run build"
49
+ },
50
+ "dependencies": {
51
+ "@clack/prompts": "catalog:"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "catalog:",
55
+ "typescript": "catalog:"
56
+ },
57
+ "type": "module",
58
+ "license": "SEE LICENSE IN LICENSE.md"
59
+ }
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: fixtures-data
3
+ description: TestSpectra test data fixtures — JSON files under fixtures/, auto-typed globally under Fixture.* with zero imports, and how to reference/refactor them from test scripts, steps, and hooks. Use whenever a test needs static mock data (credentials, catalog items, payloads, locales).
4
+ ---
5
+
6
+ # Skill: Fixture & Test Data Management
7
+
8
+ Use this skill whenever a test case, shared step, or hook needs static data — user credentials,
9
+ product catalogs, mock API payloads, localization strings.
10
+
11
+ ---
12
+
13
+ ## 1. Directory & Storage
14
+
15
+ ```
16
+ workspace-root/
17
+ └── fixtures/
18
+ ├── users.json # User roles & credential sets
19
+ ├── products.json # Catalog items & SKU metadata
20
+ ├── api-payloads.json # Mock response payloads
21
+ └── locales.json # Localization dictionaries
22
+ ```
23
+
24
+ ```json
25
+ // fixtures/users.json
26
+ {
27
+ "admin": {
28
+ "id": "usr-admin-01",
29
+ "name": "System Administrator",
30
+ "email": "admin@testspectra.dev",
31
+ "password": "Password123!",
32
+ "role": "admin"
33
+ },
34
+ "standardUser": {
35
+ "id": "usr-std-02",
36
+ "name": "Jane Doe",
37
+ "email": "jane.doe@testspectra.dev",
38
+ "password": "Password123!",
39
+ "role": "member"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 2. Ambient Typing (Zero Import)
47
+
48
+ The `TypeGenerator` watches `fixtures/` and emits `.testspectra/types/fixtures.d.ts` automatically
49
+ whenever a fixture file is created/updated:
50
+
51
+ ```typescript
52
+ declare global {
53
+ namespace Fixture {
54
+ const users: typeof import('../../fixtures/users.json');
55
+ const products: typeof import('../../fixtures/products.json');
56
+ }
57
+ }
58
+ ```
59
+
60
+ Never hand-write this file, and never `import` a fixture JSON file directly — always access it via
61
+ the global `Fixture.<fileBaseName>` namespace, exactly like Page Objects and `Step.*`.
62
+
63
+ ---
64
+
65
+ ## 3. Usage
66
+
67
+ ### In test scripts
68
+
69
+ ```typescript
70
+ it('should login with admin credentials from fixture', async () => {
71
+ await Spectra.navigate('/auth/login');
72
+ await LoginPage.emailInput.type(Fixture.users.admin.email, { clearFirst: true });
73
+ await LoginPage.passwordInput.type(Fixture.users.admin.password);
74
+ await LoginPage.submitButton.click();
75
+
76
+ await DashboardPage.welcomeMsg.shouldContainText(Fixture.users.admin.name);
77
+ });
78
+ ```
79
+
80
+ ### In shared steps
81
+
82
+ ```typescript
83
+ // support/steps/loginUser/web.step.ts
84
+ export default async function (userType: 'admin' | 'standardUser' = 'standardUser') {
85
+ const user = Fixture.users[userType];
86
+ await Spectra.navigate('/auth/login');
87
+ await LoginPage.emailInput.type(user.email, { clearFirst: true });
88
+ await LoginPage.passwordInput.type(user.password);
89
+ await LoginPage.submitButton.click();
90
+ }
91
+ ```
92
+
93
+ Fixtures are freely usable inside hooks too (e.g. `global-hooks/before` seeding a DB via `fetch`
94
+ with `Fixture.apiPayloads.seedUser`).
95
+
96
+ ---
97
+
98
+ ## 4. Renaming a Fixture
99
+
100
+ Never rename a fixture file by hand. Use:
101
+
102
+ ```
103
+ spectra refactor fixture users accounts
104
+ ```
105
+
106
+ This renames `fixtures/users.json` → `fixtures/accounts.json`, rewrites every `Fixture.users`
107
+ reference across `specs/**/*.test.ts`, `support/steps/**/*.step.ts`, and `hooks/**` to
108
+ `Fixture.accounts`, and regenerates `.testspectra/types/fixtures.d.ts` immediately with 0
109
+ TypeScript errors.