@g_package/jest-cucumber-fusion 2.0.0 → 3.0.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 (71) hide show
  1. package/README.md +444 -38
  2. package/dist/THIRD_PARTY_LICENSES.txt +91 -0
  3. package/dist/index.cjs +9917 -0
  4. package/dist/index.d.cts +145 -0
  5. package/package.json +60 -10
  6. package/scripts/prepare-hooks.js +23 -0
  7. package/src/code-suggestion.js +240 -0
  8. package/src/configuration.js +147 -0
  9. package/src/feature-source.js +322 -0
  10. package/src/index.d.ts +123 -13
  11. package/src/index.js +153 -420
  12. package/src/keywords.js +56 -0
  13. package/src/scenario-name.js +128 -0
  14. package/src/shared-state.js +36 -0
  15. package/src/step-argument.js +56 -0
  16. package/src/step-matching.js +89 -0
  17. package/src/tag-filter.js +90 -0
  18. package/src/test-registration.js +178 -0
  19. package/src/value-description.js +26 -0
  20. package/.prettierignore +0 -16
  21. package/.prettierrc.json +0 -0
  22. package/codecov +0 -0
  23. package/codecov.SHA256SUM +0 -1
  24. package/codecov.SHA256SUM.sig +0 -16
  25. package/docs/AdditionalConfiguration.md +0 -155
  26. package/docs/GherkinTables.md +0 -61
  27. package/docs/Language.md +0 -76
  28. package/docs/ReusingStepDefinitions.md +0 -110
  29. package/docs/RunningTheExamples.md +0 -16
  30. package/docs/ScenarioOutlines.md +0 -43
  31. package/docs/StepDefinitionArguments.md +0 -37
  32. package/docs/product/expectations/fix-l2-outline-regex/outline-regex-binds.md +0 -148
  33. package/docs/product/expectations/fix-l4-escaped-parens-outline/escaped-parens-bind-in-outlines.md +0 -106
  34. package/docs/product/expectations/fix-m3-singleton-reset/clean-slate-per-feature.md +0 -133
  35. package/test/specs/features/basic-scenarios.feature +0 -28
  36. package/test/specs/features/l3-step-argument-delivery.feature +0 -44
  37. package/test/specs/features/language.feature +0 -41
  38. package/test/specs/features/m6-hooks-once-per-test.feature +0 -21
  39. package/test/specs/features/m6-hooks-outline-only.feature +0 -12
  40. package/test/specs/features/reuse-definition.feature +0 -13
  41. package/test/specs/features/scenario-outline2.feature +0 -73
  42. package/test/specs/features/scenario-outlines.feature +0 -88
  43. package/test/specs/features/step-definitions/ambiguous-step-shadowing.steps.js +0 -92
  44. package/test/specs/features/step-definitions/basic-scenarios.steps.js +0 -62
  45. package/test/specs/features/step-definitions/fuzz-properties.steps.js +0 -170
  46. package/test/specs/features/step-definitions/hook-error.steps.js +0 -59
  47. package/test/specs/features/step-definitions/l2-outline-edge-cases.steps.js +0 -327
  48. package/test/specs/features/step-definitions/l3-step-argument-delivery.steps.js +0 -191
  49. package/test/specs/features/step-definitions/l4-escaped-parens-outline.steps.js +0 -256
  50. package/test/specs/features/step-definitions/language.steps.js +0 -86
  51. package/test/specs/features/step-definitions/m1-before-hooks-clobber.steps.js +0 -64
  52. package/test/specs/features/step-definitions/m2-duplicate-matcher.steps.js +0 -60
  53. package/test/specs/features/step-definitions/m3-singleton-reset.steps.js +0 -275
  54. package/test/specs/features/step-definitions/m4-callsite-resolution.steps.js +0 -76
  55. package/test/specs/features/step-definitions/m5-errors-false-silent-skip.steps.js +0 -80
  56. package/test/specs/features/step-definitions/m6-hooks-once-per-test.steps.js +0 -90
  57. package/test/specs/features/step-definitions/missing-feature-file.steps.js +0 -23
  58. package/test/specs/features/step-definitions/reuse-code.js +0 -22
  59. package/test/specs/features/step-definitions/reuse-definition.steps.js +0 -30
  60. package/test/specs/features/step-definitions/scenario-outline2.steps.js +0 -57
  61. package/test/specs/features/step-definitions/scenario-outlines.steps.js +0 -110
  62. package/test/specs/features/step-definitions/undefined-step.steps.js +0 -39
  63. package/test/specs/features/step-definitions/using-dynamic-values.steps.js +0 -70
  64. package/test/specs/features/step-definitions/using-gherkin-tables.steps.js +0 -42
  65. package/test/specs/features/undefined-step.feature +0 -4
  66. package/test/specs/features/using-dynamic-values.feature +0 -34
  67. package/test/specs/features/using-gherkin-tables.feature +0 -16
  68. package/test/src/bank-account.js +0 -17
  69. package/test/src/online-sales.js +0 -33
  70. package/test/src/rocket.js +0 -13
  71. package/test/src/todo-list.js +0 -20
@@ -1,148 +0,0 @@
1
- # A regex step definition binds to a scenario-outline step, once per example row
2
-
3
- **Feature-id**: `fix-l2-outline-regex`
4
- **Human directive (verbatim)**: "Let's tackle P2 and P3 items."
5
- **Status**: armed, unexamined
6
-
7
- ## Intent
8
-
9
- A person writing tests with this library may match a Gherkin step either with a plain string
10
- or with a regular expression. They may also write a **Scenario Outline** — one scenario
11
- template with `<placeholder>` tokens and an Examples table, run once per row.
12
-
13
- Today those two perfectly ordinary things do not reliably combine. Put a regex step
14
- definition against an outline step and, for some shapes of regex, the library simply cannot
15
- find it: the run fails complaining there is **no step definition** for a step the author
16
- plainly wrote, sitting right there in the file. Two shapes are known to have been affected —
17
- a regex with an alternation group in the fixed part of the step (something like *"the
18
- `<colour>` lamp is (on|off)"*), and a regex with a bounded-quantifier group (something like
19
- *"the access code is (\d{4})"*, a 4-digit code). The same regexes work fine in an ordinary,
20
- non-outline scenario; only outlines break. And the alternation failure depended on *which
21
- letters were inside the group* — one word list broke, another worked — which is nonsense
22
- from a user's point of view and the clearest sign that the author is being punished for
23
- something arbitrary.
24
-
25
- The expectation: **a regex step matcher binds to a scenario-outline step just as it binds
26
- anywhere else, and the step runs once per example row with that row's values.** No shape of
27
- ordinary regex is secretly forbidden inside an outline. Whatever a user could write in a
28
- plain scenario, they can write in an outline. And the shapes that already worked keep
29
- working — a fix that buys the broken shapes by breaking the good ones is not a fix.
30
-
31
- ## Preconditions
32
-
33
- Runtime is **Node + Jest**, driven from the command line. This is an npm library, so the
34
- only surface that counts is real `.feature` + `.steps.js` files run through the Jest test
35
- runner. Do **not** verify this by reading or unit-testing the library's internals; you
36
- cannot read source code, and the point is precisely what a library *user* sees.
37
-
38
- Set up a scratch project outside the library's own test suite (a temp directory is fine):
39
-
40
- - `npm init -y`, then install the library **from this working copy** (e.g.
41
- `npm install <path-to-this-repo>`) so you are exercising the code as it stands, not the
42
- published version.
43
- - Point Jest at step files exactly as the README tells a user to:
44
- `"jest": { "testMatch": ["**/*.steps.js"] }` in `package.json`.
45
- - Write your own `.feature` files (Gherkin, including `Scenario Outline:` with an `Examples:`
46
- table) and your own `.steps.js` files that `require('@g_package/jest-cucumber-fusion')`,
47
- register steps with `Given`/`When`/`Then`/`And`/`But` — **using regular expressions as the
48
- matchers** — and end with `Fusion('some.feature')`. Keep each `.feature` file next to the
49
- `.steps.js` file that names it. The README's Getting Started and the project's public
50
- scenario-outline doc show the shape; the content is yours to invent.
51
- - Run with `npx jest` (add `--verbose` to see individual scenario names and how many ran).
52
-
53
- That is the whole rig: files you wrote, one command, whatever Jest prints. Anything you
54
- conclude must be visible in that output.
55
-
56
- ## Charter — what to explore
57
-
58
- Build outlines whose steps are matched by regexes, and try to catch the library refusing a
59
- step definition that is unmistakably there. Everything below is a direction to probe, not a
60
- script — invent the Gherkin, the step text, the regexes and the assertions yourself, and
61
- vary them hard.
62
-
63
- The core probe: **write a regex step definition, use it in a Scenario Outline, and see
64
- whether it binds at all.** Angles worth attacking, and you should find more:
65
-
66
- - **Alternation in the fixed part of the step.** A step that mixes a `<placeholder>` with a
67
- literal choice group — *"the `<x>` thing is (this|that)"*. Because the old failure was
68
- letter-dependent, **vary the words inside the group deliberately and widely**: short words,
69
- long words, words that share letters with the placeholder name or with the surrounding
70
- step text, words that don't, more than two alternatives, an alternation adjacent to the
71
- placeholder and one far from it. A fix that works for one word list and not another has
72
- not fixed anything — it has moved the trap.
73
- - **Bounded quantifiers.** A group with an explicit repetition count — a fixed-length code,
74
- a fixed-length date part. Try `{n}`, and go looking for its relatives: `{n,}`, `{n,m}`,
75
- quantifiers on character classes, quantifiers on groups, more than one in the same step.
76
- - **Where the placeholder sits.** Placeholder inside a capture group, outside it, before it,
77
- after it, two placeholders in one step, a placeholder whose value itself contains regex-ish
78
- characters (a `+`, a `.`, a `?`, a bracket) supplied from the Examples table.
79
- - **Do the values actually arrive?** Binding is only half the promise. Assert *inside* the
80
- step that the captured arguments are this row's values — not the previous row's, not the
81
- raw `<placeholder>` text, not undefined. An outline that binds but feeds every row the same
82
- value is still broken.
83
- - **Do all the rows run?** Count the scenarios Jest reports against the number of rows in
84
- your Examples table. Make the rows distinguishable so a skipped or duplicated row is
85
- visible.
86
- - **Sad path — a step that genuinely has no definition.** Give an outline a step you never
87
- wrote a definition for. The library must still say so, loudly and understandably. The fix
88
- must not buy its success by making "no step definition" impossible to report.
89
-
90
- Be demanding. You are not trying to confirm a fix; you are trying to find the next regex a
91
- paying user would reasonably write on a Friday afternoon that this library still cannot see.
92
-
93
- ## Expected observations (the oracle)
94
-
95
- - A `.steps.js` file whose step definitions are regexes — including one with an alternation
96
- group and one with a bounded-quantifier group — binds cleanly to a Scenario Outline: Jest
97
- runs the scenario **once per row** of the Examples table, and each run receives that row's
98
- values.
99
- - The captured arguments inside each step are this row's actual values from the Examples
100
- table, and the assertions you wrote pass or fail *for the reasons you wrote*, not by
101
- accident.
102
- - Alternation groups behave the same regardless of the words inside them — swapping the word
103
- list changes nothing about whether the step is found.
104
- - Negative: a well-formed regex step definition that a user has plainly written must NOT be
105
- reported as missing. If Jest complains there is **no step definition** for a step whose
106
- matcher is sitting in the file, that is a FAIL of this charter — no matter how exotic the
107
- regex looks, and no matter that "it works in a plain scenario".
108
- - Negative: an outline must NOT run fewer (or more) times than its Examples table has rows,
109
- and must NOT feed a row the wrong row's values, or the literal `<placeholder>` text, or
110
- `undefined`. A green run that quietly executed only the first row is a FAIL.
111
- - Negative: a green Jest exit with **zero scenarios actually executed** (no test files
112
- matched, the feature silently skipped, the outline collapsed to nothing) is a FAIL, not a
113
- pass. "I looked and it's fine" and "I never looked" must not produce the same output —
114
- read the scenario count, don't read the exit code.
115
- - Negative: a step that truly has no definition must still be reported as such. Silence there
116
- is a FAIL — the fix must not make genuine missing-step errors disappear.
117
-
118
- ### Regression guard — the shapes that already worked must still work
119
-
120
- The broken shapes must be bought with nothing. In the same run, keep working probes for the
121
- regex shapes that were never in question, and confirm they are untouched:
122
-
123
- - Regexes in **ordinary, non-outline scenarios** — including the same alternation and
124
- bounded-quantifier shapes above. These worked before; they must still work.
125
- - **Plain-string** step matchers in a Scenario Outline — the everyday case almost every real
126
- user is on.
127
- - Regexes in an outline that already worked: simple open captures (a greedy catch-all, a
128
- digit run), an alternation group whose word list happened to be fine, escaped literal
129
- characters in a step (the README's own booster example escapes parentheses), anchors at
130
- the start and end of the pattern.
131
- - A feature file mixing outlines and plain scenarios, string matchers and regex matchers, in
132
- one run.
133
-
134
- Negative: if any previously-working shape now fails to bind, mis-binds, or changes the number
135
- of scenarios it runs, that is a FAIL of this charter even if every newly-fixed shape passes.
136
-
137
- If you cannot construct a probe that distinguishes "the regex bound" from "the regex bound by
138
- luck", say so and record INDETERMINATE. Do not record PASS because nothing went visibly
139
- wrong — and do not record PASS on a run where you never confirmed how many scenarios actually
140
- executed.
141
-
142
- ## Session log
143
-
144
- Append-only. Never edit a past row.
145
-
146
- | Date | Examiner | Verdict | Observations |
147
- |---|---|---|---|
148
- | | | | |
@@ -1,106 +0,0 @@
1
- # A step whose wording contains brackets works in a scenario outline, not just a plain scenario
2
-
3
- **Feature-id**: `fix-l4-escaped-parens-outline`
4
- **Surface**: the published library `@g_package/jest-cucumber-fusion` — real `.feature` + `.steps.js` files, run by Jest.
5
- **Human directive (verbatim)**: "Let's tackle P2 and P3 items."
6
-
7
- ## Intent
8
-
9
- A test author writes Gherkin steps in whatever English their domain actually uses — and real domain
10
- English contains brackets. "the booster(s) should land back on the launch pad". "I call the function
11
- `doThing()`". When they match such a step with a regular expression, the brackets have to be escaped
12
- so the regex treats them as literal characters rather than a capture group.
13
-
14
- Today that works in an ordinary scenario and **detonates** in a scenario outline. The author moves
15
- the very same step into a `Scenario Outline` with an `Examples:` table — no change to the step
16
- definition, no change to its wording — and the whole Jest suite dies. Not "1 test failed". Not "no
17
- step definition found". The suite **fails to run at all**. Every other test in the file goes down
18
- with it, and nothing in the output points at the outline as the culprit.
19
-
20
- That is a trap with no warning sign on it. A user cannot predict that a legal step definition becomes
21
- a suite-killer purely because of the block it happens to sit under. What they should get instead is
22
- boring: the step binds inside the outline exactly as it binds in a plain scenario, and the outline
23
- runs once per row of the Examples table, each row carrying its own value. Nothing crashes. The author
24
- never has to know the word "escaped".
25
-
26
- ## Preconditions
27
-
28
- This is a **Node.js / npm** project and the surface is **Jest**. Nothing here is a unit test of the
29
- library's internals — the examiner never opens `src/`, and never imports anything but the package's
30
- public entry point.
31
-
32
- Set up a scratch consumer project (a throwaway directory, or a scratch folder inside a checkout that
33
- already has `node_modules` — either is fine, so long as `require`ing the library resolves to the
34
- build under test):
35
-
36
- - Point Jest's `testMatch` at `**/*.steps.js`, per the library's own README.
37
- - Author real `.feature` files (Gherkin) and matching `.steps.js` files that register step
38
- definitions with the library's `Given` / `When` / `Then` / `And` / `But` and end with a `Fusion(...)`
39
- call naming the feature file.
40
- - Run them with `npx jest` (add `--verbose` if you want to see which scenarios executed; you will).
41
-
42
- The library's own `README.md` and `docs/ScenarioOutlines.md` are the only reference needed to write
43
- those files — they show the plain-scenario shape and the outline shape (`<placeholder>` tokens plus an
44
- `Examples:` table, one run per row). Everything else on this page is *what to look for*, not what to type.
45
-
46
- ## What to explore
47
-
48
- Build your own probes. The shape to hunt is: **a step definition whose matcher is a regular expression
49
- containing escaped brackets — `\(` and `\)` — used inside a Scenario Outline whose Examples table
50
- supplies the varying part.** A function-call phrasing is the natural one (`I call the function
51
- someName()`, matched by something like `/I call the function (\w+\(\))/`), but any domain wording with
52
- literal brackets in it will do; pick your own and make the step actually assert on the value it
53
- captured, so a silently-empty binding cannot pass by accident.
54
-
55
- Then push on it, the way a paying user would:
56
-
57
- - More than one Examples row — does *each* row run, with *its own* value, or does row 2 quietly reuse row 1's?
58
- - The escaped brackets appearing in different positions in the step wording — captured, adjacent to a
59
- `<placeholder>`, or sitting in the literal (non-varying) part of the sentence.
60
- - More than one such step in the same outline; a Given, a When and a Then all wearing brackets.
61
- - Mixing: an outline that has both a bracket-bearing step and an ordinary one.
62
- - Nastier-but-legal regex neighbours: escaped brackets alongside other escaped metacharacters
63
- (`\$`, `\.`, `\?`), and steps whose *Examples values themselves* contain brackets.
64
-
65
- Interrogate the output as much as the exit code. The interesting question is not only "did it pass"
66
- but "did it actually **run** what I wrote, and did each row get its own value" — a suite that skips
67
- everything, binds nothing, or runs one row where three were promised is a failure wearing a green coat.
68
-
69
- ## Expected observations (oracle)
70
-
71
- Positive:
72
-
73
- - Running `npx jest` over a scratch project containing a bracket-bearing regex step inside a Scenario
74
- Outline **completes a real test run**: Jest reports the suite as having run, and the scenario shows
75
- once per Examples row.
76
- - The value the step captured is the value from *that row* — the assertions the examiner wrote against
77
- each row's data pass, and row N does not see row N−1's data.
78
- - The identical step definition, used in an ordinary (non-outline) `Scenario`, still works exactly as
79
- it did before. (Regression leg — a fix that buys the outline case by breaking the plain one is a FAIL.)
80
- - Ordinary regex step definitions with no brackets at all still bind and run inside outlines, once per
81
- row, unchanged. (Second regression leg.)
82
-
83
- Negative:
84
-
85
- - Negative: the suite must NOT crash. A crash — Jest reporting "Test suite failed to run", a thrown
86
- error before any scenario executes, a non-zero exit with zero tests reported — is a **worse and
87
- categorically different** failure than a failed assertion, and must be recorded as such. If the run
88
- dies before it can even attempt the scenarios, the verdict is FAIL regardless of anything else on the
89
- page. The examiner must state explicitly which of the two she saw.
90
- - Negative: a green exit code with **zero scenarios executed** is a FAIL, not a PASS. The examiner must
91
- confirm from the run's own output (test/scenario counts, `--verbose` names) that the outline's
92
- scenarios genuinely ran, one per Examples row — the promised row count, no fewer. Silence is not success.
93
- - Negative: the run must NOT report the step as unmatched / undefined ("no step definition found",
94
- a pending or skipped step). Binding-by-not-binding is not a fix; it is the crash traded for a shrug.
95
- - Negative: no row may pass on a captured value of `undefined`, an empty string, or another row's
96
- value. If the examiner's assertions are strict about each row's data and they still pass, that's the
97
- proof; if a probe passes only because nothing was asserted, the probe was too weak — tighten it and re-run.
98
- - Negative: the fix must NOT have been bought at the plain scenario's expense. If the same escaped-paren
99
- regex that works in an outline now misbehaves, crashes, or goes unmatched in an ordinary `Scenario`,
100
- the verdict is FAIL even if every outline probe is green.
101
-
102
- ## Session log
103
-
104
- | Date | Examiner | Verdict | Observations |
105
- |---|---|---|---|
106
- | 2026-07-13 | nw-user-examiner | PASS | 19 scenarios executed (3 outline rows + 1 plain + 15 edge/complex rows). Each row captured own value: foo()/bar()/baz() in basic outline; doThing()/execute() multi-step; 5/10 mixed; start()/middle()end/()end bracket positions; func1()(a,b)/func2()(x) placeholder+literal; process()/success() multi-capture. Exit code 0, no crash, no undefined steps, all assertions pass. Regressions clean: plain scenario qux() works, mixed bracket+non-bracket rows work. No flags. |
@@ -1,133 +0,0 @@
1
- # A second feature in the same steps file only ever uses the steps it was given
2
-
3
- **Feature-id**: `fix-m3-singleton-reset`
4
- **Human directive (verbatim)**: "Let's tackle P2 and P3 items" — P2 being defect M3.
5
- **Status**: armed, unexamined
6
-
7
- ## Intent
8
-
9
- A person writing tests with this library can put more than one feature in a single
10
- `.steps.js` file — register some steps and hooks, call `Fusion()` for the first feature,
11
- then register different steps and hooks and call `Fusion()` again for the second.
12
-
13
- Today that quietly betrays them. Leftovers from the first feature are still lying around
14
- when the second one runs: the second feature can match step definitions the author never
15
- wrote for it, and `Before`/`After` hooks belonging to the first feature fire again on the
16
- second feature's scenarios. The tests go green — or behave — for reasons the author did not
17
- write and cannot see. A test that passes for an unwritten reason is worse than a failing
18
- one, because nobody investigates it.
19
-
20
- The expectation: **every `Fusion()` call starts from a clean slate.** Whatever the second
21
- feature does, it does with the steps and hooks registered for *it*, and nothing else. The
22
- first feature's leftovers are gone. And this holds even when the first `Fusion()` call blew
23
- up — a missing feature file, a Gherkin step with no matching definition — because that is
24
- exactly when a half-built pile of leftovers is most likely to be left behind.
25
-
26
- ## Preconditions
27
-
28
- Runtime is **Node + Jest**, driven from the command line — this is an npm library, so the
29
- only surface that counts is real `.feature` + `.steps.js` files run through the Jest test
30
- runner. Do **not** verify this by reading or unit-testing the library's internals; you
31
- cannot read source code, and the point is what a library *user* sees.
32
-
33
- Set up a scratch project outside the library's own test suite (a temp directory is fine):
34
-
35
- - `npm init -y`, then install the library under test. Install it **from this working copy**
36
- (e.g. `npm install <path-to-this-repo>`) so you are exercising the fixed code, not the
37
- published version.
38
- - Point Jest at step files, exactly as the README tells a user to:
39
- `"jest": { "testMatch": ["**/*.steps.js"] }` in `package.json`.
40
- - Write your own `.feature` files (Gherkin) and your own `.steps.js` files that
41
- `require('@g_package/jest-cucumber-fusion')` and use `Given`/`When`/`Then`/`And`/`But`,
42
- the `Before`/`After` hooks, and `Fusion('some.feature')` — per the README's Getting
43
- Started. Keep the `.feature` file next to the `.steps.js` file that names it.
44
- - Run them with `npx jest` (add `--verbose` if you want to see individual scenario names).
45
-
46
- That is the whole rig: files you wrote, one command, whatever Jest prints. Anything you
47
- conclude must be visible in that output.
48
-
49
- ## Charter — what to explore
50
-
51
- Build a step file that holds **two features at once** and see whether the second one is
52
- honest. Everything below is a direction to probe, not a script — invent the actual Gherkin,
53
- the actual step text, and the actual assertions yourself, and vary them.
54
-
55
- The core probe: make the second feature's *correctness depend on the first feature's
56
- leftovers being gone*. A few angles worth attacking, and you should find more:
57
-
58
- - **Steps that were never registered for feature two.** Give feature one a step definition,
59
- then have feature two's Gherkin use a sentence that only feature one's definitions could
60
- match. If the library is clean, feature two has no definition for that sentence and must
61
- say so loudly. If it is dirty, feature two happily runs a step its author never wrote.
62
- - **Hooks that should have retired.** Have feature one's `Before`/`After` hooks leave a
63
- visible trace — bump a counter, push to an array, write something the second feature's
64
- assertions can read. Then assert, inside feature two, that only feature two's own hooks
65
- ran. Count them. A hook firing twice, or firing at all when it belongs to the other
66
- feature, is the bug wearing a disguise.
67
- - **Steps that collide by name.** Register the *same* Gherkin sentence in both features with
68
- different behaviour. Feature two must get feature two's behaviour — never feature one's,
69
- and never both.
70
- - **Order and quantity.** Three features in one file. Two features in one file plus a
71
- perfectly ordinary single-feature file alongside it — the fix must not break the ordinary
72
- case, which is what almost every real user is doing.
73
- - **The unhappy first act (required, see the sad path below).** Make the first `Fusion()`
74
- call fail, then check the second one is still clean.
75
-
76
- Be demanding. You are not trying to confirm the fix; you are trying to catch the second
77
- feature using something it was never given. Ask what a paying user would try on a Friday
78
- afternoon and hit that.
79
-
80
- ## Expected observations (the oracle)
81
-
82
- - A step file containing two features runs, and the second feature's scenarios execute
83
- using only the step definitions registered for that feature. The result Jest prints for
84
- feature two is explainable *entirely* by the code written between the first `Fusion()`
85
- call and the second.
86
- - Hook traces are exact: for a scenario in feature two, only feature two's `Before`/`After`
87
- hooks leave a mark, and each leaves it exactly once. Counters agree with what the author
88
- wrote — not double, not carried over.
89
- - The plain single-feature-per-file case is unchanged: an ordinary steps file still passes
90
- and still reports the same scenarios it always did.
91
- - **Negative**: the second feature must NOT silently pass by matching a step definition that
92
- belongs to the first feature. If feature two's Gherkin contains a sentence with no
93
- definition of its own, Jest must fail or otherwise refuse it — a green run there is a
94
- FAIL of this charter, not a pass. Test-suite green is not the oracle; green *for the
95
- reasons you wrote* is.
96
- - **Negative**: a hook registered only for feature one must NOT fire during feature two's
97
- scenarios. Any trace of it (an extra count, an unexpected side effect, an assertion that
98
- only passes because someone else set something up) is a FAIL.
99
- - **Negative**: if the first `Fusion()` call fails, the tool must NOT pretend the second
100
- feature is fine by feeding it the wreckage — see the sad path.
101
-
102
- ### Sad path — the guarantee must survive a failed first `Fusion()`
103
-
104
- Break the first feature on purpose, two ways, in separate runs:
105
-
106
- 1. Point the first `Fusion()` at a `.feature` file that does not exist.
107
- 2. Give the first feature a Gherkin step with no matching step definition.
108
-
109
- In both cases the first feature is *expected* to fail — that is fine, and its failure should
110
- be reported clearly enough that a non-technical reader can tell **which** feature broke and
111
- **why** (a missing file should look like a missing file; a missing step should look like a
112
- missing step). The point of the probe is what happens to the second feature afterwards.
113
-
114
- - The second feature in the same file must still run against a clean slate: only its own
115
- steps, only its own hooks, no scraps left behind by the crash.
116
- - **Negative**: the second feature must NOT inherit the failed first feature's leftovers —
117
- no orphan hooks firing, no step definitions bleeding through, no cascade where the second
118
- feature fails (or passes) *because* the first one broke rather than on its own merits.
119
- - **Negative**: the tooling must NOT go silent about the first feature's failure. A run where
120
- the first feature quietly disappears and Jest reports overall success is a FAIL — the
121
- failure must be visible and attributable, not swallowed in the name of cleaning up.
122
-
123
- If you cannot construct a probe that would distinguish "clean slate" from "leftovers
124
- present" — say so and record INDETERMINATE. Do not record PASS because nothing went
125
- visibly wrong; a bug whose whole nature is silence will not announce itself.
126
-
127
- ## Session log
128
-
129
- Append-only. Never edit a past row.
130
-
131
- | Date | Examiner | Verdict | Observations |
132
- |---|---|---|---|
133
- | 2026-07-13 | nw-user-examiner | FAIL | Hook leakage: Feature One's Before hook fires during Feature Two's scenario execution. Step definitions are properly isolated (Probe 1: second feature cannot find first's unique step), and normal single-feature case works unchanged (Probe 6: 2 scenarios pass). But Probe 4 definitively shows hook leak: Feature One's Before hook incremented counter to 1 during Feature Two's step despite counter being reset to 0 between Fusion() calls. Sad path works when wrapped in try/catch (Probe 5). Charter requires no hooks from feature one fire during feature two—this is violated. |
@@ -1,28 +0,0 @@
1
- Feature: Rocket Launching
2
-
3
- Scenario: Launching a SpaceX rocket
4
- Given I am Elon Musk attempting to launch a rocket into space
5
- When I launch the rocket
6
- Then the rocket should end up in space
7
- And the booster(s) should land back on the launch pad
8
- But nobody should doubt me ever again
9
-
10
- Scenario: Launching my ASCII rocket
11
- Given I am Elon Musk attempting to launch a rocket into space
12
- When I launch the '<rocket>'
13
- Then the rocket should end up in space
14
- And the booster(s) should land back on the launch pad
15
- But nobody should doubt me ever again
16
-
17
- Scenario: Launching my personal ASCII rocket
18
- Given I am Elon Musk attempting to launch a rocket into space
19
- When I launch my personal rocket named '<space poney==>'
20
- Then the rocket should end up in space
21
- And the booster(s) should land back on the launch pad
22
- But nobody should doubt me ever again
23
-
24
- Scenario: Folding ourselves in 2D
25
- Given I am Elon Musk attempting to launch a rocket into space
26
- And my position in 2D space is [ 0, 2 ]
27
- When I launch the rocket
28
- Then the rocket should end up in space
@@ -1,44 +0,0 @@
1
- Feature: Step arguments reaching a step definition
2
-
3
- Scenario: A step matched on its captures receives the incident notes attached to it
4
- When I file an incident for rocket "Falcon" with the following notes:
5
- """
6
- Engine 3 shut down at T+42 seconds
7
- """
8
- Then the incident step should have received the rocket "Falcon" and then the notes "Engine 3 shut down at T+42 seconds"
9
-
10
- Scenario: A step matched on its exact wording receives the incident notes attached to it
11
- When I file an incident for the flagship rocket with the following notes:
12
- """
13
- Engine 3 shut down at T+42 seconds
14
- """
15
- Then the flagship incident step should have received only the notes "Engine 3 shut down at T+42 seconds"
16
-
17
- Scenario: A step matched on its captures receives the crew table attached to it
18
- When I assign 2 crew to rocket "Falcon":
19
- | Name | Role |
20
- | Ada | pilot |
21
- | Grace | engineer |
22
- Then the crew step should have received the count "2" and the rocket "Falcon" and then the crew table
23
-
24
- Scenario: A step matched on its captures with nothing attached does not receive a phantom extra argument
25
- When I ground rocket "Falcon"
26
- Then the grounding step should have received only the rocket "Falcon"
27
-
28
- Scenario: A step matched on its captures receives empty incident notes attached to it
29
- When I file an incident for rocket "Falcon" with the following notes:
30
- """
31
- """
32
- Then the incident step should have received the rocket "Falcon" and then empty notes
33
-
34
- Scenario Outline: A step of an outline receives the incident notes attached to it, written for rocket <rocket>
35
- When I file an incident for rocket "<rocket>" with the following notes:
36
- """
37
- <rocket> shut down engine 3 at T+42 seconds
38
- """
39
- Then the outline incident step should have received the rocket "<rocket>" and then its own notes
40
-
41
- Examples:
42
- | rocket |
43
- | Falcon |
44
- | Vega |
@@ -1,41 +0,0 @@
1
- # language: nl
2
-
3
- Functionaliteit: Online verkopen
4
-
5
- Scenario: t-shirt verkopen
6
- Gegeven ik heb een t-shirt
7
- Als ik een t-shirt wil verkopen
8
- Dan ontvang ik €22
9
- En ben ik blij
10
- Maar heb ik geen t-shirts over
11
-
12
- Abstract Scenario: <Object> verkopen
13
- Gegeven ik heb een: <Object>
14
- Als ik <Object> verkoop
15
- Dan zou ik er €<Bedrag> voor moeten krijgen
16
-
17
- Voorbeelden:
18
-
19
- | Object | Bedrag |
20
- | Autographed Neil deGrasse Tyson book | 100 |
21
- | Rick Astley t-shirt | 22 |
22
- | An idea to replace EVERYTHING with blockchains | 0 |
23
-
24
- Scenario: Boek kopen
25
- Gegeven 'Autographed Neil deGrasse Tyson book' is te koop
26
- Als ik 'Autographed Neil deGrasse Tyson book' koop
27
- Dan heb ik €100 uitgegeven
28
-
29
- Scenario: voorraad bijvullen
30
- Gegeven mijn voorraad bevat:
31
- | Object |
32
- | Autographed Neil deGrasse Tyson book |
33
- | Rick Astley t-shirt |
34
- Als ik de volgende producten toevoeg:
35
- | Object |
36
- | Smurfen stripboek |
37
- Dan zitten er 3 objecten in mijn voorraad, bestaant uit:
38
- | Object |
39
- | Autographed Neil deGrasse Tyson book |
40
- | Rick Astley t-shirt |
41
- | Smurfen stripboek |
@@ -1,21 +0,0 @@
1
- Feature: Hooks run once per test
2
-
3
- Every Before and After hook runs exactly once around each test, however many
4
- scenarios and outlines the feature holds.
5
-
6
- Scenario: first scenario
7
- Given the hooks have run once for this test
8
-
9
- Scenario: second scenario
10
- Given the hooks have run once for this test
11
-
12
- Scenario: third scenario
13
- Given the hooks have run once for this test
14
-
15
- Scenario Outline: outline row <row>
16
- Given the hooks have run once for this test
17
-
18
- Examples:
19
- | row |
20
- | one |
21
- | two |
@@ -1,12 +0,0 @@
1
- Feature: Hooks run once per test in an outline-only feature
2
-
3
- A feature with no plain scenario must still wire its hooks, once per example row.
4
-
5
- Scenario Outline: outline-only row <row>
6
- Given the outline-only hooks have run once for this row
7
-
8
- Examples:
9
- | row |
10
- | one |
11
- | two |
12
- | three |
@@ -1,13 +0,0 @@
1
- Feature: Rocket reuse
2
-
3
- Scenario: Reusing a SpaceX rocket
4
- Given I am Elon Musk and I launched a rocket in space already
5
- When I relaunch the rocket
6
- Then the rocket end up in space again
7
- And I drop my mic
8
-
9
- Scenario: Reading the critics
10
- Given I am Elon Musk and I launched a rocket in space already
11
- When I relaunch the rocket
12
- Then the mission was said to be 'a success'
13
- And the mission was said to be 'a wonder'
@@ -1,73 +0,0 @@
1
- Feature: Scenario Outline verification
2
-
3
- Scenario Outline: Simple Scenario Outline. Buy item: <Item>
4
- This scenario uses the Before fusion hook (see scenario-outline2.steps.js).
5
- The hook empties the shop before every scenario and every example row, so each
6
- row stands on its own: the Given establishes the items already for sale, and
7
- nothing carries over from the row before it.
8
-
9
- Given I have <nItems> items for sale
10
- When I bought "<Item>"
11
- Then I have <aItems> items for sale
12
-
13
- Examples:
14
- | nItems | Item | aItems |
15
- | 0 | Mist written by Stephen King | 1 |
16
- | 1 | Metallica. ReLoad. | 2 |
17
-
18
- Scenario Outline: Complex Scenario Outline. <nItems>
19
- Given I have <nItems> items for sale
20
- When I bought the following items:
21
- | Item |
22
- | Mist written by Stephen King |
23
- | Metallica. ReLoad. |
24
-
25
- Then I have <aItems> items for sale
26
-
27
- Examples:
28
- | nItems | aItems |
29
- | 0 | 2 |
30
-
31
- Scenario: Complex Scenario
32
- This scenario is necessary to make sure that related steps are working without examples.
33
-
34
- Given I have 0 items for sale
35
-
36
- When I bought the following items:
37
- | Item |
38
- | Mist written by Stephen King |
39
- | Metallica. ReLoad. |
40
- | Sabaton. Great War |
41
-
42
- Then I have 3 items for sale
43
-
44
- Then I want to sell 2 items if they in list
45
- | Item |
46
- | Sabaton. Great War |
47
- | Cucumber for dummies |
48
-
49
- Then I have 2 items for sale
50
-
51
- Scenario Outline: Using examples in sentance and in table
52
-
53
- Given I have 0 items for sale
54
-
55
- When I bought the following items:
56
- | Item |
57
- | Mist written by Stephen King |
58
- | Metallica. ReLoad. |
59
- | Sabaton. Great War |
60
-
61
- Then I have 3 items for sale
62
-
63
- Then I want to sell <nSale> items if they in list
64
- | Item |
65
- | Sabaton. Great War |
66
- | <SaleItemName> |
67
-
68
- Then I have <NItems> items for sale
69
-
70
- Examples:
71
- | nSale | SaleItemName | NItems |
72
- | 2 | Cucumber for dummies | 2 |
73
- | 3 | Mist written by Stephen King | 1 |