mandrel 2.40.0 → 2.41.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.
- package/.agents/README.md +2 -2
- package/.agents/instructions.md +5 -6
- package/.agents/rules/api-conventions.md +43 -7
- package/.agents/rules/ci-remediation.md +3 -14
- package/.agents/rules/gherkin-standards.md +21 -6
- package/.agents/rules/git-conventions.md +6 -5
- package/.agents/rules/security-baseline.md +6 -7
- package/.agents/rules/testing-standards.md +75 -198
- package/.agents/scripts/install-matrix-assert.js +2 -2
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +6 -0
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +139 -0
- package/.agents/scripts/lib/orchestration/epic-candidates.js +159 -0
- package/.agents/scripts/lib/orchestration/epic-checklist.js +103 -0
- package/.agents/scripts/lib/orchestration/epic-container.js +18 -2
- package/.agents/scripts/lib/orchestration/plan-context.js +97 -36
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +80 -0
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +192 -0
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +5 -1
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +164 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +14 -2
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +26 -5
- package/.agents/scripts/lib/orchestration/ticket-validator.js +11 -1
- package/.agents/scripts/plan-persist.js +60 -1
- package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +5 -10
- package/.agents/skills/core/browser-testing-with-devtools/reference.md +7 -46
- package/.agents/skills/core/code-review-and-quality/SKILL.md +0 -5
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +0 -3
- package/.agents/skills/core/gates-and-baselines/SKILL.md +10 -137
- package/.agents/skills/core/gates-and-baselines/reference.md +103 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +2 -18
- package/.agents/skills/core/security-and-hardening/SKILL.md +2 -4
- package/.agents/skills/core/security-and-hardening/reference.md +0 -70
- package/.agents/skills/skills.index.json +10 -70
- package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +4 -10
- package/.agents/skills/stack/qa/gherkin-authoring/reference.md +9 -113
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +29 -154
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +157 -98
- package/.agents/workflows/git-cleanup.md +3 -2
- package/.agents/workflows/git-deliver.md +3 -2
- package/.agents/workflows/helpers/plan-reference.md +82 -2
- package/.agents/workflows/mandrel-plan.md +45 -45
- package/.agents/workflows/qa-assist.md +20 -17
- package/.agents/workflows/qa-explore.md +30 -29
- package/.agents/workflows/qa-run.md +2 -1
- package/docs/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/.agents/rules/changelog-style.md +0 -180
- package/.agents/rules/shell-conventions.md +0 -61
- package/.agents/scripts/lib/qa/coverage-verdict.js +0 -214
- package/.agents/skills/core/api-and-interface-design/SKILL.md +0 -55
- package/.agents/skills/core/api-and-interface-design/reference.md +0 -76
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +0 -45
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +0 -56
- package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +0 -54
- package/.agents/skills/core/idea-refinement/refinement-criteria.md +0 -155
- package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +0 -15
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +0 -105
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +0 -152
- package/.agents/skills/stack/qa/vitest/SKILL.md +0 -22
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: qa-coverage-mapping
|
|
3
|
-
description:
|
|
4
|
-
Map a quality finding to a per-tier coverage verdict (unit / contract /
|
|
5
|
-
acceptance) aligned to `.agents/rules/testing-standards.md`. Use when a
|
|
6
|
-
finding points at a symbol or surface and you need to know which test tiers
|
|
7
|
-
already cover it and which are missing, so remediation lands the right tier.
|
|
8
|
-
Delegates the verdict to the deterministic
|
|
9
|
-
`lib/qa/coverage-verdict.js#coverageVerdict` helper.
|
|
10
|
-
allowed_tools:
|
|
11
|
-
- Read
|
|
12
|
-
- Bash
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# qa-coverage-mapping
|
|
16
|
-
|
|
17
|
-
## Policy Capsule
|
|
18
|
-
|
|
19
|
-
- The three-tier taxonomy (unit / contract / acceptance), tier-placement rules, and assertion-placement constraints live in `.agents/rules/testing-standards.md`; that rule is the SSOT and wins on any conflict — this skill only maps a finding onto those tiers.
|
|
20
|
-
- Compute the verdict through the deterministic helper `coverageVerdict(...)` in `.agents/scripts/lib/qa/coverage-verdict.js`; never re-derive tier placement by hand in prose.
|
|
21
|
-
- Build the `surface` input by gathering the finding's symbol and the colocated/contract/acceptance tests that exercise it — pass test paths (or `{path, tier}` descriptors) so the helper classifies each one.
|
|
22
|
-
- Read the verdict as a `{unit, contract, acceptance}` object: each tier is `{status: 'present'|'absent', note}`. A surface with only a colocated unit test reports `unit: present` and `contract`/`acceptance`: `absent` with explanatory notes.
|
|
23
|
-
- Route remediation by the absent tiers, honoring the assertion-placement rule: wire-shape and status-code gaps become **contract** tests, user-visible journey gaps become **acceptance** scenarios — never push those into unit tests or `.feature` files incorrectly.
|
|
24
|
-
- Treat `absent` as a coverage gap to surface, not an automatic failure: some surfaces legitimately need only one tier (a pure formatter needs no acceptance scenario). Use the notes to justify, not to mandate, the missing tier.
|
|
25
|
-
- This skill is read + classify only: it does not author tests, mutate tickets, or run the suite. Hand the verdict to the TDD cycle in `.agents/rules/testing-standards.md` to actually write the missing tier.
|
|
26
|
-
|
|
27
|
-
## Role
|
|
28
|
-
|
|
29
|
-
You are the coverage cartographer. Given a finding that names a code surface
|
|
30
|
-
(a symbol — function, class, or module export — plus the tests around it), you
|
|
31
|
-
produce a structured per-tier verdict that says, for each of the three test
|
|
32
|
-
tiers in [`.agents/rules/testing-standards.md`](../../../rules/testing-standards.md),
|
|
33
|
-
whether coverage is **present** or **absent**, and why. You do not write the
|
|
34
|
-
missing tests; you tell the operator (or the next skill) exactly which tier is
|
|
35
|
-
missing so remediation is aimed correctly.
|
|
36
|
-
|
|
37
|
-
## When to use
|
|
38
|
-
|
|
39
|
-
- A quality / audit finding points at a specific symbol and you need to know
|
|
40
|
-
whether it is already tested, and at which tier.
|
|
41
|
-
- Before remediating a coverage gap, to decide whether the missing test is a
|
|
42
|
-
**unit**, **contract**, or **acceptance** test (the assertion-placement rule
|
|
43
|
-
makes this decision load-bearing — a status-code gap must become a contract
|
|
44
|
-
test, not a unit test).
|
|
45
|
-
- During a test-pyramid audit, to roll up many surfaces into a tier-by-tier
|
|
46
|
-
gap report.
|
|
47
|
-
|
|
48
|
-
**When NOT to use:** for authoring tests (use the TDD cycle in
|
|
49
|
-
[`.agents/rules/testing-standards.md`](../../../rules/testing-standards.md#applying-the-standards)),
|
|
50
|
-
for measuring line/branch coverage percentages (that is the unit-tier coverage
|
|
51
|
-
config, not this skill), or for anything that requires running the suite.
|
|
52
|
-
|
|
53
|
-
## The verdict shape
|
|
54
|
-
|
|
55
|
-
`coverageVerdict(surface)` returns:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"unit": { "status": "present" | "absent", "note": "…" },
|
|
60
|
-
"contract": { "status": "present" | "absent", "note": "…" },
|
|
61
|
-
"acceptance": { "status": "present" | "absent", "note": "…" }
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
- `status` is `present` when at least one classified test exercises the surface
|
|
66
|
-
at that tier, `absent` otherwise.
|
|
67
|
-
- `note` is always populated. For `present` tiers it summarizes the count; for
|
|
68
|
-
`absent` tiers it explains the gap and echoes the symbol so the report reads
|
|
69
|
-
cleanly.
|
|
70
|
-
|
|
71
|
-
## How to apply
|
|
72
|
-
|
|
73
|
-
1. **Identify the surface.** From the finding, capture the `symbol` and the
|
|
74
|
-
list of tests that touch it — colocated `*.test.*`, anything under
|
|
75
|
-
`tests/contract/**`, and any `.feature` scenario.
|
|
76
|
-
2. **Classify and verdict.** Pass the surface to `coverageVerdict`. Each test
|
|
77
|
-
is classified by path (`.feature` → acceptance, `…/contract/…` or
|
|
78
|
-
`.contract.test.*` → contract, `.test.*` or `__tests__/` → unit) or by an
|
|
79
|
-
explicit `tier` field when you already know it.
|
|
80
|
-
3. **Read the gaps.** Every `absent` tier is a candidate gap. Apply judgment
|
|
81
|
-
from the Policy Capsule: not every surface needs all three tiers.
|
|
82
|
-
4. **Route remediation.** For real gaps, hand off to the TDD cycle in
|
|
83
|
-
`.agents/rules/testing-standards.md` with the missing tier named, honoring
|
|
84
|
-
the assertion-placement rule so each assertion lands in its correct tier.
|
|
85
|
-
|
|
86
|
-
## Example
|
|
87
|
-
|
|
88
|
-
```js
|
|
89
|
-
import { coverageVerdict } from '../../../scripts/lib/qa/coverage-verdict.js';
|
|
90
|
-
|
|
91
|
-
const verdict = coverageVerdict({
|
|
92
|
-
symbol: 'parseInvoice',
|
|
93
|
-
tests: ['src/invoice/parse-invoice.test.js'],
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// verdict.unit.status === 'present'
|
|
97
|
-
// verdict.contract.status === 'absent' // wire-shape gap → contract test
|
|
98
|
-
// verdict.acceptance.status === 'absent' // no user journey covered here
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
A colocated-unit-only surface like `parseInvoice` reports `unit` present and
|
|
102
|
-
both `contract` and `acceptance` absent with explanatory notes — exactly the
|
|
103
|
-
signal you need to decide whether the boundary (`contract`) or a user-visible
|
|
104
|
-
journey (`acceptance`) still needs a test, or whether a pure parser is
|
|
105
|
-
legitimately unit-only.
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: qa-explore-driving
|
|
3
|
-
description:
|
|
4
|
-
Conventions for agent-driven exploratory QA driving — how the agent itself
|
|
5
|
-
drives a surface during `/qa-explore` (agent-led), as opposed to the
|
|
6
|
-
human-led `/qa-assist`. Use when the agent explores a running app via the
|
|
7
|
-
browser MCP (navigation-first, the default) — including authenticated
|
|
8
|
-
deployed surfaces reached through the resolved environment's sign-in seam —
|
|
9
|
-
or walks a static surface (the documented interim where no seam resolves),
|
|
10
|
-
under a strictly read-only capture invariant. The exploration procedure lives in
|
|
11
|
-
`.agents/workflows/qa-explore.md`; this skill is the driving-conventions
|
|
12
|
-
reference it leans on.
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
# Skill: qa-explore-driving
|
|
16
|
-
|
|
17
|
-
## Policy Capsule
|
|
18
|
-
|
|
19
|
-
- Drive the running app **by default** through the browser MCP, navigation-first: start at a root and reach each surface only via UI affordances — never URL-jump to a deep link.
|
|
20
|
-
- Resolve the target **environment** at Plan time (via `resolveQaEnvironment`) and record its name in the ledger; each environment keys its own `baseUrl`, `signInSeam`, and `allowWrites`.
|
|
21
|
-
- Treat **static driving** (reading source, routes, and rendered markup without a live runtime) as the **documented interim** method, chosen at Plan time **only where no seam resolves** for the target environment — never the silent fallback.
|
|
22
|
-
- Hold the **read-only capture invariant** absolutely: the agent makes no source edits and no product mutations while driving; the only write is appending to the `temp/qa/<sessionId>` ledger.
|
|
23
|
-
- Authenticated driving follows the resolved environment's **`signInSeam`**: sign in through a dev `url` seam (persona name substituted into the template) or a `skill` seam (a stored `credentialRef` read by the named sign-in skill), with **mandatory redaction** of all captured evidence. Never type real credentials inline or fabricate a session; where an environment resolves no seam, drive the unauthenticated surface or fall back to static and record the gap.
|
|
24
|
-
- Pick the driving method explicitly in the Plan phase (drive vs. static) and record it in the ledger; do not switch methods mid-surface without a new Plan note.
|
|
25
|
-
- Every phase transition and every GitHub write is HITL-gated; the agent drives and captures, but never files or promotes findings autonomously.
|
|
26
|
-
- Broken navigation, a missing affordance, or a guard redirect loop is a **finding**, not a workaround — record it and move on; do not route around it with a direct URL.
|
|
27
|
-
- Scrub captured evidence (tokens, session cookies, PII) at the boundary via the shared redaction path before any finding reaches disk or GitHub.
|
|
28
|
-
|
|
29
|
-
Guidance for the **agent-driven** half of exploratory QA. `/qa-explore` is the
|
|
30
|
-
agent-led front-end (the agent drives, the operator watches); its human-led
|
|
31
|
-
sibling is `/qa-assist` (the human drives, the agent scribes). The exploration
|
|
32
|
-
**procedure** — argument parsing, phase gates, contract resolution, ledger
|
|
33
|
-
plumbing — is the SSOT in
|
|
34
|
-
[`qa-explore.md`](../../../../workflows/qa-explore.md); this skill shows **how**
|
|
35
|
-
to apply the driving conventions that procedure depends on. The
|
|
36
|
-
navigation-first execution and per-surface capture discipline are shared with
|
|
37
|
-
[`qa-harness`](../qa-harness/SKILL.md) (the known-scenario sweep); browser
|
|
38
|
-
instrumentation lives in
|
|
39
|
-
[`browser-testing-with-devtools`](../../../core/browser-testing-with-devtools/SKILL.md);
|
|
40
|
-
the read-only and no-PII boundaries are inviolable per
|
|
41
|
-
[`security-baseline.md`](../../../../rules/security-baseline.md). Read this
|
|
42
|
-
skill before driving a live surface; read the workflow for the phase order.
|
|
43
|
-
|
|
44
|
-
## 1. Navigation-First Driving (the default) — one prose home
|
|
45
|
-
|
|
46
|
-
Navigation-first driving is the default and load-bearing convention: reach every
|
|
47
|
-
surface the way a real user would so findings reflect a user-reachable state,
|
|
48
|
-
not an artifact of a deep link. Its full prose statement lives once in
|
|
49
|
-
[`qa-run-scenario.md`](../../../../workflows/helpers/qa-run-scenario.md) (shared
|
|
50
|
-
with the known-scenario sweep) — apply it from there rather than restating it.
|
|
51
|
-
In capsule:
|
|
52
|
-
|
|
53
|
-
- **Drive the running app by default** through the browser MCP; static (§ 2) is
|
|
54
|
-
the interim alternative, not the norm.
|
|
55
|
-
- **Start at a root and never URL-jump** — reach the surface under test by
|
|
56
|
-
clicking the affordances a real user has, never by deep-linking a starting
|
|
57
|
-
state.
|
|
58
|
-
- **Broken navigation is a finding, not a workaround** — a missing affordance, a
|
|
59
|
-
nav 404, or a guard redirect loop is recorded; do not route around it.
|
|
60
|
-
- **Observe, do not fabricate** — never script the runtime to manufacture an
|
|
61
|
-
outcome the exploration is meant to discover.
|
|
62
|
-
|
|
63
|
-
## 2. Static Driving — the Documented Interim
|
|
64
|
-
|
|
65
|
-
Static driving is the **explicitly documented interim** method for when **no
|
|
66
|
-
seam resolves** for the target environment — the resolved environment carries
|
|
67
|
-
no `signInSeam` the agent can drive through (§ 4). It walks the surface from
|
|
68
|
-
source, route definitions, and rendered markup rather than a running browser.
|
|
69
|
-
|
|
70
|
-
- **Choose it at Plan time, never silently.** Static is a deliberate Plan-phase
|
|
71
|
-
decision recorded in the ledger ("environment: preview, method: static,
|
|
72
|
-
reason: no seam resolves"), not an unannounced fallback the agent slips into
|
|
73
|
-
when the browser MCP hiccups.
|
|
74
|
-
- **It is interim, not equivalent.** Static driving cannot exercise real
|
|
75
|
-
authorization, routing guards, or runtime console/network signal. Treat its
|
|
76
|
-
coverage as partial and say so in the ledger; a static pass does not close the
|
|
77
|
-
same coverage a driven pass would.
|
|
78
|
-
- **Same read-only invariant.** Static driving reads source and routes; it makes
|
|
79
|
-
no edits. The read-only capture invariant (§ 3) applies identically.
|
|
80
|
-
- **Promote to driving when a seam lands.** Static is the bridge until the
|
|
81
|
-
target environment resolves a `signInSeam` (§ 4) that makes driven
|
|
82
|
-
authenticated exploration possible. When that lands, re-run the surface
|
|
83
|
-
driven; do not leave a surface permanently static when it could be driven.
|
|
84
|
-
|
|
85
|
-
## 3. The Read-Only Capture Invariant
|
|
86
|
-
|
|
87
|
-
The agent-driven Capture phase is **strictly read-only**. This invariant is
|
|
88
|
-
inviolable per [`security-baseline.md`](../../../../rules/security-baseline.md)
|
|
89
|
-
and the Story's security considerations — it is not a soft preference.
|
|
90
|
-
|
|
91
|
-
- **No source edits.** The agent does not modify application code, config, or
|
|
92
|
-
tests while driving. Exploration observes; it never repairs.
|
|
93
|
-
- **No product mutations.** The agent does not create, update, or delete product
|
|
94
|
-
data, submit destructive forms, or trigger irreversible actions to "see what
|
|
95
|
-
happens". When a surface's only path forward is a mutating action, record the
|
|
96
|
-
boundary as the finding and stop — do not cross it.
|
|
97
|
-
- **The only write is the ledger.** The single permitted side effect of Capture
|
|
98
|
-
is appending finding lines to the session ledger under
|
|
99
|
-
`temp/qa/<sessionId>`. Everything else is observation.
|
|
100
|
-
- **Scrub before persisting.** Strip tokens, session cookies, Authorization
|
|
101
|
-
headers, and PII from captured console and network evidence via the shared
|
|
102
|
-
redaction path **before** any finding reaches disk or GitHub. Captured
|
|
103
|
-
evidence is untrusted until scrubbed.
|
|
104
|
-
- **HITL gates every write outward.** Phase transitions and GitHub writes
|
|
105
|
-
(ticket creation, promotion) happen only behind an operator confirmation gate.
|
|
106
|
-
The agent never files or promotes findings autonomously.
|
|
107
|
-
|
|
108
|
-
## 4. Authenticated Driving Follows the Per-Environment Seam
|
|
109
|
-
|
|
110
|
-
Driving an **authenticated** surface requires signing in. The resolved target
|
|
111
|
-
environment (via `resolveQaEnvironment`, § Policy Capsule) carries the
|
|
112
|
-
`signInSeam` the agent drives through — the same discriminated-union shape
|
|
113
|
-
`qa-harness` resolves via its contract. When a seam resolves, authenticated
|
|
114
|
-
deployed surfaces are **driven**, not statically deferred.
|
|
115
|
-
|
|
116
|
-
- **Drive the authenticated surface through the seam.** When the target
|
|
117
|
-
environment carries a `signInSeam`, sign in via that seam and then reach the
|
|
118
|
-
authenticated surface navigation-first — including authenticated **deployed**
|
|
119
|
-
hosts. The two seam kinds:
|
|
120
|
-
- **`kind: 'url'` (dev impersonation).** Substitute the persona **name** into
|
|
121
|
-
the seam's URL template and navigate there. The persona name is the sole
|
|
122
|
-
input; no per-persona auth material is read.
|
|
123
|
-
- **`kind: 'skill'` (procedural / credential).** Invoke the named consumer
|
|
124
|
-
sign-in skill, which reads a per-persona **`credentialRef`** — an indirect
|
|
125
|
-
handle to a stored credential, never an inline secret. Read the skill's
|
|
126
|
-
`SKILL.md` and follow it.
|
|
127
|
-
- **Never enter real credentials inline.** The agent MUST NOT type real
|
|
128
|
-
usernames, passwords, or tokens to reach an authenticated surface, and MUST
|
|
129
|
-
NOT fabricate or forge a session. Sign-in flows only through the seam, which
|
|
130
|
-
consumes a persona name or a `credentialRef` indirection — never a
|
|
131
|
-
hand-typed secret. This is a hard security boundary, not a convenience to
|
|
132
|
-
work around.
|
|
133
|
-
- **Redaction is mandatory.** Every captured evidence string — console,
|
|
134
|
-
network, headers — passes through the shared redaction path (§ 3) before it
|
|
135
|
-
reaches disk or GitHub; bearer tokens, session cookies, `Authorization`
|
|
136
|
-
headers, and PII are masked. Authenticated driving raises the stakes on
|
|
137
|
-
redaction, it does not relax it.
|
|
138
|
-
- **Static only where no seam resolves.** When the target environment resolves
|
|
139
|
-
**no** `signInSeam`, drive only the unauthenticated surface or fall back to
|
|
140
|
-
static driving (§ 2), and record the gap in the ledger so the partial
|
|
141
|
-
coverage is visible. A surface that could not be driven because the
|
|
142
|
-
environment carries no seam is itself a coverage signal worth recording, not
|
|
143
|
-
a silent skip.
|
|
144
|
-
|
|
145
|
-
## 5. Cross-References
|
|
146
|
-
|
|
147
|
-
- Run procedure (SSOT): [`qa-explore.md`](../../../../workflows/qa-explore.md).
|
|
148
|
-
- Driving rules (one prose home): [`qa-run-scenario.md`](../../../../workflows/helpers/qa-run-scenario.md).
|
|
149
|
-
- Known-scenario sibling sweep: [`qa-harness`](../qa-harness/SKILL.md).
|
|
150
|
-
- Browser instrumentation: [`browser-testing-with-devtools`](../../../core/browser-testing-with-devtools/SKILL.md).
|
|
151
|
-
- Read-only / no-PII boundary: [`security-baseline.md`](../../../../rules/security-baseline.md).
|
|
152
|
-
- Assertion-tier rules: [`testing-standards.md`](../../../../rules/testing-standards.md).
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vitest
|
|
3
|
-
description:
|
|
4
|
-
Writes fast, isolated unit and integration tests with Vitest. Use when each
|
|
5
|
-
test must run on file-save without shared state — `vi.mock()` for external
|
|
6
|
-
deps, `vi.spyOn()` for call monitoring, AAA structure, and edge-case
|
|
7
|
-
coverage for null/undefined/boundary inputs.
|
|
8
|
-
vendor: vitest
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Skill: Vitest
|
|
12
|
-
|
|
13
|
-
## Policy Capsule
|
|
14
|
-
|
|
15
|
-
- Keep each test independent — never share mutable state between tests; reset mocks in `afterEach`.
|
|
16
|
-
- Mock external dependencies with `vi.mock()`; use `vi.spyOn()` only to observe call shape, not to replace logic.
|
|
17
|
-
- Structure tests as Arrange / Act / Assert — do not interleave the three phases.
|
|
18
|
-
- Use descriptive titles in the `describe('Component', () => { it('should [action] when [condition]') })` form.
|
|
19
|
-
- Cover error paths, null/undefined inputs, and boundary conditions, not just the happy path.
|
|
20
|
-
- Use snapshots only for large, stable data structures; avoid them for frequently changing UI to prevent snapshot fatigue.
|
|
21
|
-
- Aim for 80%+ coverage on business logic and edge cases; audit with `vitest --coverage`.
|
|
22
|
-
- Test observable behavior, not internal implementation details; refactors should not require rewriting passing tests.
|