@cepharum/contextual-gherkin 4.0.0 → 4.0.2

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 (2) hide show
  1. package/llms.txt +137 -0
  2. package/package.json +1 -1
package/llms.txt ADDED
@@ -0,0 +1,137 @@
1
+ # @cepharum/contextual-gherkin
2
+
3
+ > Flexible, context-aware Gherkin step definitions for Playwright-based E2E tests. Requires v3+.
4
+ > Full documentation: https://cepharum-foss.gitlab.io/contextual-gherkin/
5
+
6
+ ## What it does
7
+
8
+ contextual-gherkin provides a large library of ready-made Cucumber step definitions and a development API for writing custom ones. Its key feature is *contextuality*: a step that finds elements can track them so a follow-up step can act on them without repeating the selector logic.
9
+
10
+ ## Setup (one-time per project)
11
+
12
+ ```javascript
13
+ // steps/setup.js
14
+ import { BeforeAll, Before } from "@cucumber/cucumber";
15
+ import { ContextualGherkin, use } from "@cepharum/contextual-gherkin";
16
+
17
+ let adapter;
18
+
19
+ BeforeAll( async () => {
20
+ adapter = await use.playwright(); // launches browser once
21
+ } );
22
+
23
+ Before( () => ContextualGherkin( {
24
+ selectors: {
25
+ button: "button",
26
+ panel: { "": ".panel", button: ".panel__btn" },
27
+ },
28
+ aliases: { btn: "button" },
29
+ }, adapter ) );
30
+ ```
31
+
32
+ Use `Before({ tags: "@tag" })` to provide different configurations per Cucumber tag.
33
+
34
+ ## Selectors configuration
35
+
36
+ ### Regular selectors
37
+ Map singular element names to CSS selectors (or Playwright extended selectors):
38
+ ```javascript
39
+ button: "button"
40
+ panel: "#main > .panel"
41
+ item: "xpath=//li[@data-active]"
42
+ ```
43
+
44
+ ### Selector hierarchies
45
+ Nest selectors so context-specific overrides apply automatically:
46
+ ```javascript
47
+ menu: {
48
+ "": "#menu", // selector for "menu" itself
49
+ item: "a", // "item" inside a menu → <a>
50
+ },
51
+ overview: {
52
+ "": ".overview",
53
+ item: "li", // "item" inside overview → <li>
54
+ },
55
+ item: "li", // global fallback for "item"
56
+ ```
57
+
58
+ ### Virtual selectors
59
+ Customise how built-in steps inspect parts/properties of matched elements:
60
+ - `$label` — element representing the label (default: `"label"`)
61
+ - `$text` — element representing textual content (default: `false` = self)
62
+ - `$click`, `$enter`, `$hover` — target for action steps (default: `false` = self)
63
+ - `$checked`, `$disabled`, `$value`, `$id`, `$name`, `$selected`, `$classList`
64
+ - `@attrName` — redirect attribute inspection to a different attribute
65
+ - `#propName` — redirect DOM property inspection to a different property
66
+
67
+ ### Custom selectors (cg-*)
68
+ All registered automatically. Use anywhere a selector string is accepted:
69
+
70
+ | Selector | Meaning |
71
+ |---|---|
72
+ | `cg-property=name:value` | DOM property exact/regex match |
73
+ | `cg-attribute=name:value` | HTML attribute exact/regex match |
74
+ | `cg-list-property=classList:foo` | classList contains "foo" |
75
+ | `cg-list-property=classList!foo` | classList does not contain "foo" |
76
+ | `cg-width=200` / `>=200` / `<=200` | rendered width in px |
77
+ | `cg-height=200` / `>=200` / `<=200` | rendered height in px |
78
+ | `cg-shadow-query=:shadow .inner` | query across shadow DOM boundary |
79
+ | `me=` | the context element itself |
80
+
81
+ `cg-shadow-query`: `:shadow` is a boundary token (not a CSS pseudo-class). A leading `:shadow` enters the context element's own shadow root. Multiple `:shadow` tokens cross multiple boundaries.
82
+
83
+ ## Accessing the API in custom steps
84
+
85
+ ```javascript
86
+ import { Given, Then } from "@cucumber/cucumber";
87
+ import { ContextualGherkin } from "@cepharum/contextual-gherkin";
88
+
89
+ // Global search — find elements anywhere on page
90
+ Then( "there is/are {cardinal-word} with a width of {int}px", async ( query, width ) => {
91
+ const api = await ContextualGherkin();
92
+ const matches = await api.find( query.word ).filterBySelector( `cg-width=${width}` );
93
+ await matches.checkCardinalWord( query );
94
+ } );
95
+
96
+ // Contextual search — find elements relative to a previous match
97
+ Then( "{contextual-word} has/have a width of {int}px", async ( term, width ) => {
98
+ const api = await ContextualGherkin();
99
+ const context = api.getContextFor( term );
100
+ const box = await context.locator.boundingBox();
101
+ if ( box?.width !== width ) throw new Error( `expected ${width}px, got ${box?.width}` );
102
+ } );
103
+ ```
104
+
105
+ **Important**: Cucumber step callbacks receive one argument per Cucumber expression token — never use array destructuring, as `fn.length` is used for arity validation.
106
+
107
+ ## Key context methods
108
+
109
+ | Method | Description |
110
+ |---|---|
111
+ | `context.find( name, fallback? )` | search descendants by configured type name |
112
+ | `context.filterByType( name )` | intersect current set with named type (tests elements themselves) |
113
+ | `context.filterBySelector( sel )` | intersect current set with raw selector |
114
+ | `context.filterBySubType( name )` | keep elements that *contain* a descendant of named type |
115
+ | `context.filterBySubSelector( sel )` | keep elements that *contain* a descendant matching selector |
116
+ | `context.nth( index )` | pick single element by zero-based index |
117
+ | `context.withAttribute( name, value )` | filter by attribute value |
118
+ | `context.withProperty( name, value )` | filter by DOM property value |
119
+ | `context.checkCardinalWord( query )` | assert count and track in history |
120
+ | `context.track( type?, cardinality? )` | manually track in history |
121
+ | `context.locator` | underlying Playwright Locator |
122
+
123
+ ## Cucumber expressions provided
124
+
125
+ - `{cardinal-word}` — e.g. "three buttons", "at least 2 icons" → `{ word, number, mode, cardinality }`
126
+ - `{contextual-word}` — e.g. "this button", "the first icon" → `{ word, index, subIndex, ... }`
127
+ - `{ordinal-word}` — e.g. "the third" → `{ word, index }`
128
+ - `{string-or-word}` — quoted string or single word
129
+
130
+ ## Aliases
131
+
132
+ ```javascript
133
+ aliases: {
134
+ btn: "button", // "btn" ↔ "button"
135
+ list: [ "menu", "overview", "sidebar" ] // all four alias each other
136
+ }
137
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cepharum/contextual-gherkin",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "flexible step definitions for Gherkin",
5
5
  "author": "cepharum GmbH <thomas.urban@cepharum.de>",
6
6
  "homepage": "https://cepharum-foss.gitlab.io/contextual-gherkin/",