executable-stories-playwright 7.0.1 → 7.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "executable-stories-playwright",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.2",
|
|
4
4
|
"description": "BDD-style executable stories for Playwright Test with documentation generation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
23
|
-
"
|
|
23
|
+
"skills",
|
|
24
|
+
"README.md",
|
|
25
|
+
"bin"
|
|
24
26
|
],
|
|
25
27
|
"peerDependencies": {
|
|
26
28
|
"@playwright/test": ">=1.58.2",
|
|
27
|
-
"executable-stories-formatters": "^0.6.
|
|
29
|
+
"executable-stories-formatters": "^0.6.2",
|
|
28
30
|
"autotel": ">=2.21.0"
|
|
29
31
|
},
|
|
30
32
|
"peerDependenciesMeta": {
|
|
@@ -39,7 +41,7 @@
|
|
|
39
41
|
"@types/node": "^25.3.2",
|
|
40
42
|
"tsup": "^8.5.1",
|
|
41
43
|
"typescript": "~5.9.3",
|
|
42
|
-
"executable-stories-formatters": "0.6.
|
|
44
|
+
"executable-stories-formatters": "0.6.2"
|
|
43
45
|
},
|
|
44
46
|
"repository": {
|
|
45
47
|
"type": "git",
|
|
@@ -53,6 +55,9 @@
|
|
|
53
55
|
"documentation",
|
|
54
56
|
"executable-stories"
|
|
55
57
|
],
|
|
58
|
+
"bin": {
|
|
59
|
+
"intent": "./bin/intent.js"
|
|
60
|
+
},
|
|
56
61
|
"scripts": {
|
|
57
62
|
"build": "tsup",
|
|
58
63
|
"type-check": "tsc --noEmit",
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-converting-tests
|
|
3
|
+
description: >
|
|
4
|
+
Incrementally adopt executable-stories in Playwright. Add story.init(testInfo)
|
|
5
|
+
and step markers to existing spec blocks. File naming .story.spec.ts.
|
|
6
|
+
TestInfo from test callback second argument. Progressive enhancement.
|
|
7
|
+
type: lifecycle
|
|
8
|
+
library: executable-stories-playwright
|
|
9
|
+
library_version: "7.0.1"
|
|
10
|
+
requires:
|
|
11
|
+
- playwright-story-api
|
|
12
|
+
sources:
|
|
13
|
+
- "jagreehal/executable-stories:apps/docs-site/src/content/docs/guides/converting-playwright.md"
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
This skill builds on playwright-story-api. Read playwright-story-api first.
|
|
17
|
+
|
|
18
|
+
# Converting Existing Playwright Tests
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
Install the packages and configure the reporter:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install -D executable-stories-playwright executable-stories-formatters
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// playwright.config.ts
|
|
30
|
+
import { defineConfig } from "@playwright/test";
|
|
31
|
+
|
|
32
|
+
export default defineConfig({
|
|
33
|
+
reporter: [
|
|
34
|
+
["html"],
|
|
35
|
+
["executable-stories-playwright/reporter", { formats: ["markdown"] }],
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Core Patterns
|
|
41
|
+
|
|
42
|
+
### Step 1: Rename the file
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
# Before
|
|
46
|
+
tests/login.spec.ts
|
|
47
|
+
|
|
48
|
+
# After
|
|
49
|
+
tests/login.story.spec.ts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Step 2: Add story.init() and step markers
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// Before
|
|
56
|
+
import { test, expect } from "@playwright/test";
|
|
57
|
+
|
|
58
|
+
test("logs in successfully", async ({ page }) => {
|
|
59
|
+
await page.goto("/login");
|
|
60
|
+
await page.fill("#email", "user@example.com");
|
|
61
|
+
await page.fill("#password", "secret");
|
|
62
|
+
await page.click("#submit");
|
|
63
|
+
await expect(page.locator("h1")).toHaveText("Dashboard");
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// After
|
|
69
|
+
import { test, expect } from "@playwright/test";
|
|
70
|
+
import { story, given, when, then } from "executable-stories-playwright";
|
|
71
|
+
|
|
72
|
+
test("logs in successfully", async ({ page }, testInfo) => {
|
|
73
|
+
story.init(testInfo);
|
|
74
|
+
|
|
75
|
+
given("the login page is loaded");
|
|
76
|
+
await page.goto("/login");
|
|
77
|
+
|
|
78
|
+
when("valid credentials are entered");
|
|
79
|
+
await page.fill("#email", "user@example.com");
|
|
80
|
+
await page.fill("#password", "secret");
|
|
81
|
+
await page.click("#submit");
|
|
82
|
+
|
|
83
|
+
then("the dashboard is shown");
|
|
84
|
+
await expect(page.locator("h1")).toHaveText("Dashboard");
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Key change: add `testInfo` as the second parameter in the test callback.
|
|
89
|
+
|
|
90
|
+
### Step 3: Minimal story
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
test("loads homepage", async ({ page }, testInfo) => {
|
|
94
|
+
story.init(testInfo);
|
|
95
|
+
await page.goto("/");
|
|
96
|
+
await expect(page).toHaveTitle("My App");
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Step 4: Add doc entries
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
test("shows product details", async ({ page }, testInfo) => {
|
|
104
|
+
story.init(testInfo, { tags: ["e2e", "products"] });
|
|
105
|
+
|
|
106
|
+
given("the product page is loaded");
|
|
107
|
+
await page.goto("/products/123");
|
|
108
|
+
|
|
109
|
+
then("the product details are shown");
|
|
110
|
+
story.screenshot({ path: "screenshots/product.png", alt: "Product page" });
|
|
111
|
+
story.json({ label: "Product", value: { id: 123, name: "Widget" } });
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Suite headings from test.describe
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
test.describe("Authentication", () => {
|
|
119
|
+
test("valid login", async ({ page }, testInfo) => {
|
|
120
|
+
story.init(testInfo);
|
|
121
|
+
// "Authentication" becomes a ## heading in docs
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Common Mistakes
|
|
127
|
+
|
|
128
|
+
### HIGH Using .story.test.ts instead of .story.spec.ts
|
|
129
|
+
|
|
130
|
+
Wrong: `tests/login.story.test.ts`
|
|
131
|
+
Correct: `tests/login.story.spec.ts`
|
|
132
|
+
|
|
133
|
+
Playwright convention uses `.spec.ts`. The reporter filters accordingly.
|
|
134
|
+
|
|
135
|
+
Source: CLAUDE.md — file naming conventions
|
|
136
|
+
|
|
137
|
+
### HIGH Forgetting testInfo parameter
|
|
138
|
+
|
|
139
|
+
Wrong:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
test("my test", async ({ page }) => {
|
|
143
|
+
story.init(); // No testInfo
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Correct:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
test("my test", async ({ page }, testInfo) => {
|
|
151
|
+
story.init(testInfo);
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`testInfo` is the second parameter of Playwright's test callback. Without it, story metadata is not linked to the test.
|
|
156
|
+
|
|
157
|
+
Source: packages/executable-stories-playwright/src/story-api.ts
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-reporter-setup
|
|
3
|
+
description: >
|
|
4
|
+
Configure Playwright custom reporter for executable-stories-playwright.
|
|
5
|
+
playwright.config.ts reporter array. Default export from
|
|
6
|
+
executable-stories-playwright/reporter. Output formats, directory, naming.
|
|
7
|
+
Aggregated and colocated modes. rawRunPath for CLI.
|
|
8
|
+
type: core
|
|
9
|
+
library: executable-stories-playwright
|
|
10
|
+
library_version: "7.0.1"
|
|
11
|
+
sources:
|
|
12
|
+
- "jagreehal/executable-stories:packages/executable-stories-playwright/src/reporter.ts"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# executable-stories-playwright — Reporter Setup
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// playwright.config.ts
|
|
21
|
+
import { defineConfig } from "@playwright/test";
|
|
22
|
+
|
|
23
|
+
export default defineConfig({
|
|
24
|
+
reporter: [
|
|
25
|
+
["html"],
|
|
26
|
+
[
|
|
27
|
+
"executable-stories-playwright/reporter",
|
|
28
|
+
{
|
|
29
|
+
formats: ["markdown", "html"],
|
|
30
|
+
outputDir: "docs",
|
|
31
|
+
outputName: "user-stories",
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Peer dependency: `executable-stories-formatters` must be installed.
|
|
39
|
+
|
|
40
|
+
## Core Patterns
|
|
41
|
+
|
|
42
|
+
### Minimal config
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
export default defineConfig({
|
|
46
|
+
reporter: [
|
|
47
|
+
["html"],
|
|
48
|
+
["executable-stories-playwright/reporter", { formats: ["markdown"] }],
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Full options
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
export default defineConfig({
|
|
57
|
+
reporter: [
|
|
58
|
+
["html"],
|
|
59
|
+
[
|
|
60
|
+
"executable-stories-playwright/reporter",
|
|
61
|
+
{
|
|
62
|
+
formats: ["markdown", "html", "junit", "cucumber-json"],
|
|
63
|
+
outputDir: "reports",
|
|
64
|
+
outputName: "test-results",
|
|
65
|
+
output: {
|
|
66
|
+
mode: "aggregated",
|
|
67
|
+
},
|
|
68
|
+
markdown: {
|
|
69
|
+
title: "User Stories",
|
|
70
|
+
includeStatusIcons: true,
|
|
71
|
+
includeErrors: true,
|
|
72
|
+
includeMetadata: true,
|
|
73
|
+
sortScenarios: "source",
|
|
74
|
+
},
|
|
75
|
+
html: {
|
|
76
|
+
title: "Test Report",
|
|
77
|
+
darkMode: true,
|
|
78
|
+
searchable: true,
|
|
79
|
+
embedScreenshots: true,
|
|
80
|
+
},
|
|
81
|
+
rawRunPath: "reports/raw-run.json",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Annotation-based metadata
|
|
89
|
+
|
|
90
|
+
The reporter reads story metadata from test annotations with `type: "story-meta"`. This is handled automatically when using `story.init(testInfo)` — no manual annotation is needed.
|
|
91
|
+
|
|
92
|
+
## Common Mistakes
|
|
93
|
+
|
|
94
|
+
### HIGH Using default export syntax incorrectly
|
|
95
|
+
|
|
96
|
+
Wrong:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import StoryReporter from "executable-stories-playwright/reporter";
|
|
100
|
+
|
|
101
|
+
export default defineConfig({
|
|
102
|
+
reporter: [
|
|
103
|
+
["html"],
|
|
104
|
+
[new StoryReporter({ formats: ["markdown"] })],
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Correct:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
export default defineConfig({
|
|
113
|
+
reporter: [
|
|
114
|
+
["html"],
|
|
115
|
+
[
|
|
116
|
+
"executable-stories-playwright/reporter",
|
|
117
|
+
{ formats: ["markdown"] },
|
|
118
|
+
],
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Playwright's reporter config expects a string path and options object tuple, not a class instance. Playwright instantiates the reporter itself from the path.
|
|
124
|
+
|
|
125
|
+
Source: packages/executable-stories-playwright/src/reporter.ts
|
|
126
|
+
|
|
127
|
+
### MEDIUM Default format is cucumber-json, not markdown
|
|
128
|
+
|
|
129
|
+
The default `formats` is `["cucumber-json"]`. Always specify `formats: ["markdown"]` explicitly to get readable markdown output.
|
|
130
|
+
|
|
131
|
+
Source: packages/executable-stories-playwright/src/reporter.ts
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: playwright-story-api
|
|
3
|
+
description: >
|
|
4
|
+
Write BDD stories in Playwright using executable-stories-playwright.
|
|
5
|
+
Top-level exports with TestInfo: story.init(testInfo). Async steps with
|
|
6
|
+
fixtures ({ page }). Steps: given, when, then, and, but. Doc entries:
|
|
7
|
+
json, kv, code, table, link, section, mermaid, screenshot, note, tag.
|
|
8
|
+
Auto-And keyword conversion. Aliases: arrange, act, assert.
|
|
9
|
+
type: core
|
|
10
|
+
library: executable-stories-playwright
|
|
11
|
+
library_version: "7.0.1"
|
|
12
|
+
sources:
|
|
13
|
+
- "jagreehal/executable-stories:packages/executable-stories-playwright/src/story-api.ts"
|
|
14
|
+
- "jagreehal/executable-stories:apps/docs-site/src/content/docs/playwright/playwright-story-api.md"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# executable-stories-playwright — Story API
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { test, expect } from "@playwright/test";
|
|
23
|
+
import { story, given, when, then } from "executable-stories-playwright";
|
|
24
|
+
|
|
25
|
+
test.describe("Login page", () => {
|
|
26
|
+
test("authenticates with valid credentials", async ({ page }, testInfo) => {
|
|
27
|
+
story.init(testInfo, { tags: ["auth"], ticket: "AUTH-42" });
|
|
28
|
+
|
|
29
|
+
given("the login page is loaded");
|
|
30
|
+
await page.goto("/login");
|
|
31
|
+
|
|
32
|
+
when("valid credentials are entered");
|
|
33
|
+
await page.fill("#email", "alice@example.com");
|
|
34
|
+
await page.fill("#password", "secret");
|
|
35
|
+
await page.click('button[type="submit"]');
|
|
36
|
+
|
|
37
|
+
then("the dashboard is shown");
|
|
38
|
+
await expect(page.locator("h1")).toHaveText("Dashboard");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
File naming: `*.story.spec.ts`.
|
|
44
|
+
|
|
45
|
+
Playwright uses top-level step exports. `story.init(testInfo)` requires the `testInfo` parameter from the test callback.
|
|
46
|
+
|
|
47
|
+
## Core Patterns
|
|
48
|
+
|
|
49
|
+
### Top-level step exports with fixtures
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { story, given, when, then, and, but } from "executable-stories-playwright";
|
|
53
|
+
|
|
54
|
+
test("blocks suspended user login", async ({ page }, testInfo) => {
|
|
55
|
+
story.init(testInfo);
|
|
56
|
+
|
|
57
|
+
given("the user account exists"); // renders "Given"
|
|
58
|
+
given("the account is suspended"); // renders "And" (auto-converted)
|
|
59
|
+
when("the user submits valid credentials");
|
|
60
|
+
await page.fill("#email", "user@test.com");
|
|
61
|
+
await page.click("#submit");
|
|
62
|
+
|
|
63
|
+
then("the user sees an error message");
|
|
64
|
+
await expect(page.locator(".error")).toBeVisible();
|
|
65
|
+
|
|
66
|
+
but("the user is not logged in"); // renders "But" (always)
|
|
67
|
+
await expect(page).toHaveURL("/login");
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Doc entries with screenshots
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
test("checkout flow", async ({ page }, testInfo) => {
|
|
75
|
+
story.init(testInfo);
|
|
76
|
+
|
|
77
|
+
given("a cart with items");
|
|
78
|
+
story.json({ label: "Cart", value: { items: 3, total: 150 } });
|
|
79
|
+
|
|
80
|
+
when("the user completes checkout");
|
|
81
|
+
await page.click("#checkout");
|
|
82
|
+
await page.waitForURL("/confirmation");
|
|
83
|
+
|
|
84
|
+
then("the confirmation page is shown");
|
|
85
|
+
story.screenshot({ path: "screenshots/confirmation.png", alt: "Order confirmation" });
|
|
86
|
+
story.table({
|
|
87
|
+
label: "Order details",
|
|
88
|
+
columns: ["Item", "Qty", "Price"],
|
|
89
|
+
rows: [["Widget", "3", "$50"]],
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Step wrappers with timing
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const response = await story.fn("When", "the API is called", async () => {
|
|
98
|
+
return page.request.get("/api/data");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await story.expect("the response is successful", async () => {
|
|
102
|
+
expect(response.status()).toBe(200);
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Suite headings from test.describe
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
test.describe("Authentication", () => {
|
|
110
|
+
test("valid login", async ({ page }, testInfo) => {
|
|
111
|
+
story.init(testInfo);
|
|
112
|
+
// Produces "## Authentication" heading in generated docs
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Suite path comes from `testInfo.titlePath`. Describe titles become `##` headings in generated docs.
|
|
118
|
+
|
|
119
|
+
## Common Mistakes
|
|
120
|
+
|
|
121
|
+
### CRITICAL Missing testInfo argument in story.init()
|
|
122
|
+
|
|
123
|
+
Wrong:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
test("my test", async ({ page }) => {
|
|
127
|
+
story.init();
|
|
128
|
+
given("something");
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Correct:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
test("my test", async ({ page }, testInfo) => {
|
|
136
|
+
story.init(testInfo);
|
|
137
|
+
given("something");
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Without `testInfo`, story metadata is not linked to the test. The `testInfo` parameter must be the second argument in the Playwright test callback.
|
|
142
|
+
|
|
143
|
+
Source: packages/executable-stories-playwright/src/story-api.ts
|
|
144
|
+
|
|
145
|
+
### HIGH Using .story.test.ts file extension
|
|
146
|
+
|
|
147
|
+
Wrong:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
tests/login.story.test.ts
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Correct:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
tests/login.story.spec.ts
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Playwright uses `.spec.ts` by convention. The reporter filters for `.story.spec.ts` files. Using `.test.ts` may cause the reporter to miss story metadata.
|
|
160
|
+
|
|
161
|
+
Source: CLAUDE.md — "Story test files use .story.spec.ts (playwright)"
|
|
162
|
+
|
|
163
|
+
### HIGH Forgetting testInfo in callback destructuring
|
|
164
|
+
|
|
165
|
+
Wrong:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
test("my test", async ({ page }) => {
|
|
169
|
+
story.init(testInfo); // testInfo is undefined
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Correct:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
test("my test", async ({ page }, testInfo) => {
|
|
177
|
+
story.init(testInfo);
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`testInfo` is the second parameter of the Playwright test callback, not a fixture. It must be explicitly named after the fixtures object.
|
|
182
|
+
|
|
183
|
+
Source: packages/executable-stories-playwright/src/story-api.ts
|
|
184
|
+
|
|
185
|
+
### MEDIUM Calling steps before story.init()
|
|
186
|
+
|
|
187
|
+
Wrong:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
test("my test", async ({ page }, testInfo) => {
|
|
191
|
+
given("something");
|
|
192
|
+
story.init(testInfo);
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Correct:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
test("my test", async ({ page }, testInfo) => {
|
|
200
|
+
story.init(testInfo);
|
|
201
|
+
given("something");
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Steps called before `init()` are silently dropped because no story context exists.
|
|
206
|
+
|
|
207
|
+
Source: packages/eslint-plugin-executable-stories-playwright/src/rules/require-story-context-for-steps.ts
|