test-casebook 1.0.0 → 1.0.1

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.
@@ -1,50 +1,57 @@
1
1
  ---
2
2
  name: test-task
3
- description: Use when a project manager wants to turn a story into a complete, shared test task before development — reads the story, reads the real permission/data model as source of truth, interviews the PM one question at a time to close gaps (personas, gated capabilities, regression surface, edge cases), and writes a test-task.md that both the front and back developers will execute. Triggers on "turn this story into a test task", "découper une tâche test", "plan the tests for this story", "what should we test for STK-xxxx", or a pasted/linked story.
3
+ description: Use when a project manager wants to turn a story into test tasks in Jira before development — reads the whole story, interviews the PM one question at a time to close gaps (personas, gated capabilities and their forbidden side, regression surface, edge cases), then creates one Jira sub-task per team (front / back / mobile) carrying the behavioural test contract that team's developer will execute. Triggers on "turn this story into a test task", "crée la tâche test", "découper une tâche test", "plan the tests for STK-xxxx", or a linked/pasted story.
4
4
  ---
5
5
 
6
- # test-task — story → shared test task
6
+ # test-task — story → test sub-tasks in Jira
7
7
 
8
- You help a **project manager** turn one story into a single, complete **test task** the contract that the front and back developers each hand to their own agent (the `test-casebook` skill) to validate their work. The point is to close the two holes a story alone leaves: **which actor** performs each action (permissions / multi-role), and **regressions** in adjacent areas.
8
+ You help a **project manager** turn one story into **test tasks in Jira** — one **sub-task per team** (front / back / mobile), each carrying the behavioural contract its developer will hand to the `test-casebook` skill. You write **intent, never code** (no PHPUnit, no Vitest, no Flutter) *what* must be true per actor, not *how* to test it. Each team then executes its own sub-task.
9
9
 
10
- The output is **`test-task.md`**: behavioural, layer-agnostic cases. It is *not* the per-unit `task-test.md` a developer's `test-casebook` run produces — it is the **intent** that run derives its expected outcomes from.
10
+ You close the two holes a story alone leaves: **which actor** performs each action (permissions / multi-role) and **regressions** in adjacent areas.
11
+
12
+ > Runs in Claude Code (with the Atlassian/Jira tools) or as a **Claude Desktop project** with the Jira connector enabled. In Desktop you have no repo access — you rely on the story plus the PM interview, not on reading code.
11
13
 
12
14
  ## Do this, in order
13
15
 
14
- 1. **Get the story.** If given an issue key, fetch it (Jira tool); otherwise ask the PM to paste it. Read acceptance criteria, scope, and linked context.
15
- 2. **Read the real model, don't just trust the story.** Open the relevant code especially the **permission/role model** (the backend is the source of truth) and the data shapes. The PM knows the business need; the model tells you which roles, scopes, and capabilities actually exist. Enumerate from what you read, not from the story's prose.
16
- 3. **Interview the PM to close gaps one question at a time.** Focus on what a story omits:
17
- - which **personas** are in play (each = a role set + scope: global / per-tenant-or-BU / resource-owner);
18
- - for each capability the story adds or touches, **who may and who must not** — get the *forbidden* side explicitly;
19
- - what **adjacent areas** this story could break (the regression surface);
20
- - edge cases, empty/error states, boundaries the criteria don't mention.
21
- Ask the highest-value ambiguity first; don't batch a wall of questions.
22
- 4. **Write `test-task.md`.** For every scenario × persona, state the **expected observable outcome** (allowed / refused), not "has permission X". Rules:
23
- - **Dense on the refused cells** for each gated capability, at least one persona that must be denied.
24
- - **Both layers** for permission cases — the API must refuse (e.g. 403) **and** the UI must reflect it (control absent/disabled). Name the `data-test-*` hook each UI case will select on where known.
25
- - **Expected comes from intent** (this document), never to be recomputed from the app's own check downstream.
26
- - **Point outward for regressions** list the adjacent flows to re-verify because this story touches them.
27
- - Note per case whether it's front, back, or both, so each developer sees their slice.
28
- 5. **Confirm with the PM**, then save `test-task.md`. This one file goes to both developers.
29
-
30
- ## Shape of `test-task.md`
16
+ 1. **Get the whole story.** Given an issue key, fetch it via the Jira tool (description, acceptance criteria, epic, links, components). Read all of it.
17
+ 2. **Interview the PM to close gaps one question at a time**, highest-value ambiguity first (never a wall of questions):
18
+ - which **personas** are in playeach a role set + scope (global / per-tenant-or-BU / resource-owner);
19
+ - for every capability the story adds or touches, **who may and who must not** always pin the **forbidden** side explicitly;
20
+ - which **adjacent areas** this story could break (the regression surface);
21
+ - edge cases, empty / error states, boundaries the criteria skip.
22
+ 3. **Decide the teams** the story touches (front / back / mobile) usually not all three.
23
+ 4. **Build one internal matrix** `persona × scenario → expected observable outcome` (allowed / refused), then **split it into one sub-task per team**. Deriving all sub-tasks from the *same* matrix is what keeps front and back from drifting on what a persona is or what's expected.
24
+ 5. **Create the Jira sub-tasks** (issue type **Sub-task** unless the project uses a custom one confirm against the project's issue types), each **linked to the parent story**:
25
+ - **label = the team** (`front` / `back` / `mobile`);
26
+ - **assignee = the specific developer**ask the PM who takes each team; if unknown, leave it unassigned (never guess);
27
+ - each sub-task **self-contained**: it restates the personas and the expected outcomes for *its* layer, so the developer needn't read the sibling sub-tasks.
28
+ 6. **Confirm the plan with the PM** before creating anything in Jira, then create the sub-tasks.
31
29
 
32
- ```md
33
- # Test task — <story>
30
+ ## What each sub-task contains
31
+
32
+ Behavioural cases, expressed as outcomes — never "has permission X":
34
33
 
34
+ - **Dense on the refused cells** — for every gated capability, at least one persona that must be **denied**.
35
+ - **State the layer's observable outcome** — back sub-task: API result (e.g. `member-simple → POST /merge-requests → 403`); front sub-task: UI result (e.g. create control absent — name the `data-test-*` hook where known).
36
+ - **Both layers must agree** — the same persona/scenario appears in the front *and* back sub-task with matching intent; a front/back disagreement at execution time is the bug this is meant to surface.
37
+ - **Expected comes from intent** (this contract), never to be recomputed downstream from the app's own check.
38
+ - **Regression surface** — list the adjacent flows to re-verify because this story touches them.
39
+
40
+ Example (front sub-task body):
41
+
42
+ ```md
35
43
  ## Personas
36
44
  - member-simple: role "member" on BU-1
37
- - bu-admin-multi: role "bu-admin" on BU-1 + "member" on BU-2
45
+ - bu-admin-multi: "bu-admin" on BU-1 + "member" on BU-2
38
46
 
39
- ## Scenario: create a merge request
40
- - [ ] bu-admin-multi → ALLOWED MR created (back: 201 · front: create button visible, data-test: mr-create)
41
- - [ ] member-simple → REFUSED — back: 403 · front: create button absent (data-test: mr-create) [front+back]
47
+ ## Create a merge request (front)
48
+ - [ ] bu-admin-multi → create control visible + usable (data-test: mr-create)
49
+ - [ ] member-simple → create control ABSENT (data-test: mr-create) refused cell
42
50
 
43
- ## Regression surface (re-verify — this story touches permissions on MR)
44
- - [ ] MR list still loads for member-simple
45
- - [ ] existing MR detail actions unchanged for bu-admin-multi
51
+ ## Regression (this story touches MR permissions)
52
+ - [ ] MR list still renders for member-simple
46
53
  ```
47
54
 
48
- ## Prerequisite
55
+ ## Prerequisite — flag it, don't paper over it
49
56
 
50
- The refused/allowed cells are only real if each developer can **instantiate the personas** (a factory / token minter). If the project has none, flag it in `test-task.md` so it's built before the cells are trusted — see the persona matrix in `AGENTS.md` (Step 5.2). Do not paper over it.
57
+ The refused/allowed cells are only real if each developer can **instantiate the personas** (a factory / token minter). If a team has none, say so in its sub-task so it's built before the cells are trusted — see the persona matrix in `AGENTS.md` (Step 5.2).
package/AGENTS.md CHANGED
@@ -229,6 +229,8 @@ Type every stub / handler to the real signature (Pass B step 3) — a stub that
229
229
  - treat third-party components and the framework runtime as trusted boundaries — assert on **your** inputs to them and **your** handling of their outputs, not their internals;
230
230
  - exclude framework / vendor / generated code from coverage (`coverage.exclude`) so the 90% measures only the code you wrote.
231
231
 
232
+ **Some effects aren't observable at unit level — send them to E2E, don't fake them.** A headless DOM (jsdom / happy-dom) does not compute layout or fully apply styling: CSS custom properties injected via `v-bind()` / `useCssVars`, values from real stylesheets, geometry, and paint are not serialized. If a case's only observable effect is one of these (e.g. a `fontSize` prop that just feeds a CSS variable), it **cannot** be asserted in a unit test. Do not select on a rendered style that the runner never produced, and do not invent a passing assertion. Cover the prop's *render* branches at unit level, assert the visual effect in **E2E**, and leave a one-line note on the skipped unit assertion per Step 5.0 — the same honesty rule as a genuinely unreachable path.
233
+
232
234
  ### Step 5.2 — Permission-gated units: the persona matrix
233
235
 
234
236
  When a unit's behaviour depends on **who** the current user is — a role, a permission, an ownership / tenant / scope check — one happy-path user is not a test. This is the single biggest source of escaped bugs, because a harness that always authenticates as the same user (or only ever mints single-role users) never exercises the other actors. Apply this whenever Step 5.0 flagged an authorization gate.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "test-casebook",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Testing methodology and AI-agent playbook for exhaustive, data-test-driven test suites",
5
5
  "author": "techmefr",
6
6
  "license": "MIT",