@esimplicitylabs/katalyst-xspec 0.6.0 → 0.7.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/README.md +7 -3
- package/cli/init.cjs +85 -96
- package/cli/upgrade.cjs +63 -1
- package/dist/{chunk-ACAXOGKZ.js → chunk-UTTKW2SR.js} +106 -165
- package/dist/index.d.ts +6 -3
- package/dist/index.js +3 -4
- package/dist/steps/index.d.ts +0 -9
- package/dist/steps/index.js +1 -1
- package/package.json +1 -1
- package/skills/katalyst-bdd-architecture/SKILL.md +10 -9
- package/skills/katalyst-bdd-architecture/references/custom-steps.md +15 -19
- package/skills/katalyst-bdd-create-test/SKILL.md +34 -29
- package/skills/katalyst-bdd-create-test/references/api-patterns.md +0 -15
- package/skills/katalyst-bdd-create-test/references/hybrid-patterns.md +1 -14
- package/skills/katalyst-bdd-create-test/references/tui-patterns.md +3 -27
- package/skills/katalyst-bdd-create-test/references/ui-patterns.md +0 -19
- package/skills/katalyst-bdd-quickstart/SKILL.md +57 -55
- package/skills/katalyst-bdd-step-reference/SKILL.md +15 -19
- package/skills/katalyst-bdd-step-reference/references/api-steps.md +1 -2
- package/skills/katalyst-bdd-step-reference/references/shared-steps.md +1 -5
- package/skills/katalyst-bdd-step-reference/references/tui-steps.md +7 -5
- package/skills/katalyst-bdd-step-reference/references/ui-steps.md +1 -2
- package/skills/katalyst-bdd-troubleshooting/SKILL.md +23 -24
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as playwright_bdd from 'playwright-bdd';
|
|
2
2
|
export { test as baseTest } from 'playwright-bdd';
|
|
3
3
|
import * as _playwright_test from '@playwright/test';
|
|
4
|
-
import { APIResponse, PlaywrightTestArgs, PlaywrightWorkerArgs,
|
|
4
|
+
import { APIResponse, APIRequestContext, PlaywrightTestArgs, PlaywrightWorkerArgs, Page } from '@playwright/test';
|
|
5
5
|
export { isFlagEnabled, registerAllSteps, registerApiAssertionSteps, registerApiAuthSteps, registerApiHttpSteps, registerApiSteps, registerDebugSteps, registerFlagSteps, registerFormSteps, registerHybridSteps, registerHybridSuite, registerLayoutSteps, registerSharedCleanupSteps, registerSharedSteps, registerSharedVarSteps, registerTuiBasicSteps, registerTuiSteps, registerTuiWizardSteps, registerUiAuthSteps, registerUiBasicSteps, registerUiSteps, registerWizardSteps, setFlag } from './steps/index.js';
|
|
6
6
|
|
|
7
7
|
type CleanupItem = {
|
|
@@ -685,11 +685,14 @@ declare function createOidcCleanupAuth(config?: OidcCleanupAuthConfig): CleanupA
|
|
|
685
685
|
declare function resetOidcCleanupAuth(): void;
|
|
686
686
|
|
|
687
687
|
type TagsForProjectInput = {
|
|
688
|
-
|
|
688
|
+
/** Optional tag a project is limited to, e.g. '@smoke'. Not needed for the built-in steps. */
|
|
689
|
+
projectTag?: string;
|
|
690
|
+
/** Extra tag expression, typically from `resolveExtraTags(process.env.TEST_TAGS)`. */
|
|
689
691
|
extraTags?: string;
|
|
690
692
|
defaultExcludes?: string;
|
|
691
693
|
};
|
|
692
|
-
|
|
694
|
+
/** Build a playwright-bdd `tags` expression: default excludes, optional project tag, optional extra tags. */
|
|
695
|
+
declare function tagsForProject({ projectTag, extraTags, defaultExcludes }?: TagsForProjectInput): string;
|
|
693
696
|
declare function resolveExtraTags(raw?: string | null): string | undefined;
|
|
694
697
|
|
|
695
698
|
/**
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
setupBypassAuth,
|
|
35
35
|
setupFetchIntercept,
|
|
36
36
|
tryParseJson
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-UTTKW2SR.js";
|
|
38
38
|
|
|
39
39
|
// src/fixtures.ts
|
|
40
40
|
import { test as base } from "playwright-bdd";
|
|
@@ -972,9 +972,8 @@ function resetOidcCleanupAuth() {
|
|
|
972
972
|
}
|
|
973
973
|
|
|
974
974
|
// src/config.ts
|
|
975
|
-
function tagsForProject({ projectTag, extraTags, defaultExcludes = "not @Skip and not @ignore" }) {
|
|
976
|
-
|
|
977
|
-
return `${defaultExcludes} and ${projectTag}`;
|
|
975
|
+
function tagsForProject({ projectTag, extraTags, defaultExcludes = "not @Skip and not @ignore" } = {}) {
|
|
976
|
+
return [defaultExcludes, projectTag, extraTags && `(${extraTags})`].filter(Boolean).join(" and ");
|
|
978
977
|
}
|
|
979
978
|
function resolveExtraTags(raw) {
|
|
980
979
|
const tagFilterRaw = raw?.trim();
|
package/dist/steps/index.d.ts
CHANGED
|
@@ -36,7 +36,6 @@ declare function registerWizardSteps(test: any): void;
|
|
|
36
36
|
* UI Form Step Definitions
|
|
37
37
|
*
|
|
38
38
|
* Steps for bulk form filling using Gherkin data tables.
|
|
39
|
-
* Tagged with @ui or @hybrid for selective execution.
|
|
40
39
|
*/
|
|
41
40
|
declare function registerFormSteps(test: any): void;
|
|
42
41
|
|
|
@@ -44,7 +43,6 @@ declare function registerFormSteps(test: any): void;
|
|
|
44
43
|
* UI Debug Step Definitions
|
|
45
44
|
*
|
|
46
45
|
* Steps for debugging and troubleshooting UI tests.
|
|
47
|
-
* Tagged with @ui or @hybrid for selective execution.
|
|
48
46
|
*/
|
|
49
47
|
declare function registerDebugSteps(test: any): void;
|
|
50
48
|
|
|
@@ -52,7 +50,6 @@ declare function registerDebugSteps(test: any): void;
|
|
|
52
50
|
* UI Layout Assertion Step Definitions
|
|
53
51
|
*
|
|
54
52
|
* Steps for asserting layout states like panels, split views, and responsive behavior.
|
|
55
|
-
* Tagged with @ui or @hybrid for selective execution.
|
|
56
53
|
*/
|
|
57
54
|
declare function registerLayoutSteps(test: any): void;
|
|
58
55
|
|
|
@@ -60,7 +57,6 @@ declare function registerLayoutSteps(test: any): void;
|
|
|
60
57
|
* UI Auth Step Definitions
|
|
61
58
|
*
|
|
62
59
|
* Steps for authenticating in UI tests using fetch interception.
|
|
63
|
-
* Tagged with @ui for selective execution.
|
|
64
60
|
*/
|
|
65
61
|
declare function registerUiAuthSteps(test: any): void;
|
|
66
62
|
|
|
@@ -68,7 +64,6 @@ declare function registerUiAuthSteps(test: any): void;
|
|
|
68
64
|
* TUI Basic Step Definitions
|
|
69
65
|
*
|
|
70
66
|
* Basic step definitions for terminal user interface testing.
|
|
71
|
-
* Tagged with @tui for selective execution.
|
|
72
67
|
* Aligned with ui.basic.ts patterns for consistency.
|
|
73
68
|
*/
|
|
74
69
|
declare function registerTuiBasicSteps(test: any): void;
|
|
@@ -77,19 +72,16 @@ declare function registerTuiBasicSteps(test: any): void;
|
|
|
77
72
|
* TUI Wizard Step Definitions
|
|
78
73
|
*
|
|
79
74
|
* Advanced step definitions for terminal user interface testing.
|
|
80
|
-
* Tagged with @tui for selective execution.
|
|
81
75
|
* Aligned with ui.wizard.ts patterns for consistency.
|
|
82
76
|
*/
|
|
83
77
|
declare function registerTuiWizardSteps(test: any): void;
|
|
84
78
|
|
|
85
79
|
/**
|
|
86
80
|
* Register all API step definitions.
|
|
87
|
-
* Steps are tagged with @api or @hybrid for selective execution.
|
|
88
81
|
*/
|
|
89
82
|
declare function registerApiSteps(test: any): void;
|
|
90
83
|
/**
|
|
91
84
|
* Register all UI step definitions.
|
|
92
|
-
* Steps are tagged with @ui or @hybrid for selective execution.
|
|
93
85
|
*
|
|
94
86
|
* Includes:
|
|
95
87
|
* - Basic UI steps (navigation, clicks, fills)
|
|
@@ -116,7 +108,6 @@ declare function registerSharedSteps(test: any): void;
|
|
|
116
108
|
declare function registerHybridSuite(test: any): void;
|
|
117
109
|
/**
|
|
118
110
|
* Register all TUI (Terminal User Interface) step definitions.
|
|
119
|
-
* Steps are tagged with @tui for selective execution.
|
|
120
111
|
*
|
|
121
112
|
* @example
|
|
122
113
|
* ```typescript
|
package/dist/steps/index.js
CHANGED
package/package.json
CHANGED
|
@@ -164,7 +164,7 @@ const test = createBddTest({
|
|
|
164
164
|
```typescript
|
|
165
165
|
createApi: (ctx) => {
|
|
166
166
|
ctx.apiRequest; // Playwright APIRequestContext
|
|
167
|
-
ctx.page; // Playwright Page
|
|
167
|
+
ctx.page; // Playwright Page
|
|
168
168
|
// Return your ApiPort implementation
|
|
169
169
|
}
|
|
170
170
|
|
|
@@ -192,14 +192,14 @@ When('I do something with {string}', async ({ world }, param: string) => {
|
|
|
192
192
|
world.vars['result'] = param;
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
-
// Step
|
|
196
|
-
When('I make API call',
|
|
195
|
+
// Step using the API fixture (no tags needed; works in any scenario)
|
|
196
|
+
When('I make API call', async ({ api, world }) => {
|
|
197
197
|
const result = await api.sendJson('GET', '/endpoint');
|
|
198
198
|
world.lastJson = result.json;
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
// Step with multiple fixtures
|
|
202
|
-
When('I verify in both layers',
|
|
202
|
+
When('I verify in both layers', async ({ api, ui, world }) => {
|
|
203
203
|
await api.sendJson('POST', '/data', { value: 'test' });
|
|
204
204
|
await ui.goto('/data');
|
|
205
205
|
await ui.expectText('test');
|
|
@@ -481,13 +481,14 @@ selectPath(data, 'user.roles[0]'); // 'admin'
|
|
|
481
481
|
```typescript
|
|
482
482
|
import { tagsForProject, resolveExtraTags } from '@esimplicitylabs/katalyst-xspec';
|
|
483
483
|
|
|
484
|
-
// Build tag expression with defaults
|
|
485
|
-
|
|
486
|
-
|
|
484
|
+
// Build tag expression with defaults (projects select features by folder;
|
|
485
|
+
// tags only skip @Skip/@ignore and apply optional TEST_TAGS)
|
|
486
|
+
tagsForProject();
|
|
487
|
+
// Result: 'not @Skip and not @ignore'
|
|
487
488
|
|
|
488
489
|
// With extra tags
|
|
489
|
-
tagsForProject({
|
|
490
|
-
//
|
|
490
|
+
tagsForProject({ extraTags: resolveExtraTags(process.env.TEST_TAGS) });
|
|
491
|
+
// e.g. TEST_TAGS=@smoke -> 'not @Skip and not @ignore and (@smoke)'
|
|
491
492
|
```
|
|
492
493
|
|
|
493
494
|
## File Organization
|
|
@@ -82,7 +82,7 @@ When I POST "/users" with JSON body:
|
|
|
82
82
|
```typescript
|
|
83
83
|
import { DataTable } from '@cucumber/cucumber';
|
|
84
84
|
|
|
85
|
-
When('I fill the form:', async ({ ui }, dataTable: DataTable) => {
|
|
85
|
+
When('I fill the signup form:', async ({ ui }, dataTable: DataTable) => {
|
|
86
86
|
const rows = dataTable.hashes();
|
|
87
87
|
// rows = [{ Field: 'Email', Value: 'test@...' }, ...]
|
|
88
88
|
|
|
@@ -94,7 +94,7 @@ When('I fill the form:', async ({ ui }, dataTable: DataTable) => {
|
|
|
94
94
|
|
|
95
95
|
**Usage:**
|
|
96
96
|
```gherkin
|
|
97
|
-
When I fill the form:
|
|
97
|
+
When I fill the signup form:
|
|
98
98
|
| Field | Value |
|
|
99
99
|
| Email | test@example.com |
|
|
100
100
|
| Password | secret123 |
|
|
@@ -120,30 +120,26 @@ const pairs = dataTable.rowsHash();
|
|
|
120
120
|
// { Email: '...', Password: '...' }
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
##
|
|
123
|
+
## Step Scope
|
|
124
|
+
|
|
125
|
+
Custom steps don't need `{ tags: ... }`. Like the built-in steps, a step without tags works in any scenario, whichever fixtures it uses:
|
|
124
126
|
|
|
125
127
|
```typescript
|
|
126
|
-
|
|
127
|
-
When('I make an API call', { tags: '@api' }, async ({ api }) => {
|
|
128
|
+
When('I make an API call', async ({ api }) => {
|
|
128
129
|
// ...
|
|
129
130
|
});
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
When('I GET {string}', { tags: '@api or @hybrid' }, async ({ api, world }, path) => {
|
|
132
|
+
When('I click something', async ({ ui }) => {
|
|
133
133
|
// ...
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
When('I click something', { tags: '@ui' }, async ({ ui }) => {
|
|
136
|
+
When('I create via API and check in UI', async ({ api, ui, world }) => {
|
|
138
137
|
// ...
|
|
139
138
|
});
|
|
140
|
-
|
|
141
|
-
// Available everywhere (no tag restriction)
|
|
142
|
-
Given('I set variable {string} to {string}', async ({ world }, name, value) => {
|
|
143
|
-
world.vars[name] = value;
|
|
144
|
-
});
|
|
145
139
|
```
|
|
146
140
|
|
|
141
|
+
Don't reuse wording of a built-in step (e.g. `I GET {string}`, `I set variable {string} to {string}`); a step text that matches two definitions is ambiguous.
|
|
142
|
+
|
|
147
143
|
## Available Fixtures
|
|
148
144
|
|
|
149
145
|
Steps receive these fixtures:
|
|
@@ -285,7 +281,7 @@ import { expect } from '@playwright/test';
|
|
|
285
281
|
* Custom steps for report generation testing
|
|
286
282
|
*/
|
|
287
283
|
|
|
288
|
-
When('I generate a {string} report',
|
|
284
|
+
When('I generate a {string} report',
|
|
289
285
|
async ({ api, world }, reportType: string) => {
|
|
290
286
|
const result = await api.sendJson('POST', '/reports/generate', {
|
|
291
287
|
type: reportType,
|
|
@@ -301,7 +297,7 @@ When('I generate a {string} report', { tags: '@api or @hybrid' },
|
|
|
301
297
|
}
|
|
302
298
|
);
|
|
303
299
|
|
|
304
|
-
When('I wait for the report to complete',
|
|
300
|
+
When('I wait for the report to complete',
|
|
305
301
|
async ({ api, world }) => {
|
|
306
302
|
const reportId = world.vars['reportId'];
|
|
307
303
|
let attempts = 0;
|
|
@@ -323,7 +319,7 @@ When('I wait for the report to complete', { tags: '@api or @hybrid' },
|
|
|
323
319
|
}
|
|
324
320
|
);
|
|
325
321
|
|
|
326
|
-
Then('the report should be downloadable',
|
|
322
|
+
Then('the report should be downloadable',
|
|
327
323
|
async ({ api, world }) => {
|
|
328
324
|
const reportUrl = world.vars['reportUrl'];
|
|
329
325
|
expect(reportUrl).toBeDefined();
|
|
@@ -334,14 +330,14 @@ Then('the report should be downloadable', { tags: '@api or @hybrid' },
|
|
|
334
330
|
}
|
|
335
331
|
);
|
|
336
332
|
|
|
337
|
-
When('I view the report in the UI',
|
|
333
|
+
When('I view the report in the UI',
|
|
338
334
|
async ({ ui, world }) => {
|
|
339
335
|
const reportId = world.vars['reportId'];
|
|
340
336
|
await ui.goto(`/reports/${reportId}`);
|
|
341
337
|
}
|
|
342
338
|
);
|
|
343
339
|
|
|
344
|
-
Then('I should see the report preview',
|
|
340
|
+
Then('I should see the report preview',
|
|
345
341
|
async ({ ui }) => {
|
|
346
342
|
await ui.expectText('Report Preview');
|
|
347
343
|
await ui.expectElementState('first', 'pdf-viewer', 'locator', 'visible');
|
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: katalyst-bdd-create-test
|
|
3
|
-
description: Create BDD tests for the Katalyst framework. Use when writing new feature files, creating test scenarios, choosing test
|
|
3
|
+
description: Create BDD tests for the Katalyst framework. Use when writing new feature files, creating test scenarios, choosing where to put a test (features/api, features/ui, features/tui) or mixing API and UI steps, or implementing common testing patterns like CRUD operations, login flows, form handling, or API+UI verification workflows.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Katalyst BDD Test Creation Guide
|
|
7
7
|
|
|
8
8
|
This skill guides you through creating BDD tests with the Katalyst framework.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Where to Put a Test
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Steps are untagged: any step works in any scenario. Do NOT add `@api`/`@ui`/`@hybrid`/`@tui` tags or `{ tags: ... }` on steps. Each Playwright project picks feature files by folder, so just choose the folder:
|
|
13
13
|
|
|
14
14
|
```
|
|
15
15
|
What are you testing?
|
|
16
16
|
│
|
|
17
|
-
├─ HTTP API only →
|
|
17
|
+
├─ HTTP API only → features/api/
|
|
18
18
|
│ (REST endpoints, JSON responses, status codes)
|
|
19
19
|
│
|
|
20
|
-
├─ Browser UI only →
|
|
20
|
+
├─ Browser UI only → features/ui/
|
|
21
21
|
│ (Pages, forms, buttons, navigation)
|
|
22
22
|
│
|
|
23
|
-
├─ Terminal UI only →
|
|
23
|
+
├─ Terminal UI only → features/tui/ (enable the tui project first)
|
|
24
24
|
│ (CLI apps, interactive terminal programs)
|
|
25
25
|
│
|
|
26
|
-
└─
|
|
26
|
+
└─ API + UI in one scenario → features/ui/ (it needs a browser)
|
|
27
27
|
(Create via API, verify in UI)
|
|
28
28
|
(Setup data, then test UI flows)
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
Tags are optional and only for the user's own grouping (`@smoke`, `@wip`, `@regression`).
|
|
32
|
+
|
|
31
33
|
## Feature File Structure
|
|
32
34
|
|
|
33
35
|
Every feature file follows this structure:
|
|
34
36
|
|
|
35
37
|
```gherkin
|
|
36
|
-
|
|
38
|
+
# Tags are optional; this one is your own grouping
|
|
39
|
+
@smoke
|
|
37
40
|
Feature: Feature Name
|
|
38
41
|
As a [role]
|
|
39
42
|
I want [capability]
|
|
@@ -48,14 +51,13 @@ Feature: Feature Name
|
|
|
48
51
|
Then [expected outcome]
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
## Creating API Tests
|
|
54
|
+
## Creating API Tests
|
|
52
55
|
|
|
53
56
|
### Step 1: Create Feature File
|
|
54
57
|
|
|
55
58
|
Location: `features/api/[resource].feature`
|
|
56
59
|
|
|
57
60
|
```gherkin
|
|
58
|
-
@api
|
|
59
61
|
Feature: [Resource] API
|
|
60
62
|
As a developer
|
|
61
63
|
I want to test the [Resource] API
|
|
@@ -126,14 +128,13 @@ Scenario: Full [resource] lifecycle
|
|
|
126
128
|
|
|
127
129
|
See [API Patterns](references/api-patterns.md) for more examples.
|
|
128
130
|
|
|
129
|
-
## Creating UI Tests
|
|
131
|
+
## Creating UI Tests
|
|
130
132
|
|
|
131
133
|
### Step 1: Create Feature File
|
|
132
134
|
|
|
133
135
|
Location: `features/ui/[page].feature`
|
|
134
136
|
|
|
135
137
|
```gherkin
|
|
136
|
-
@ui
|
|
137
138
|
Feature: [Page Name]
|
|
138
139
|
As a user
|
|
139
140
|
I want to [action on page]
|
|
@@ -176,14 +177,13 @@ Scenario: User login
|
|
|
176
177
|
|
|
177
178
|
See [UI Patterns](references/ui-patterns.md) for more examples.
|
|
178
179
|
|
|
179
|
-
## Creating TUI Tests
|
|
180
|
+
## Creating TUI Tests
|
|
180
181
|
|
|
181
182
|
### Step 1: Create Feature File
|
|
182
183
|
|
|
183
184
|
Location: `features/tui/[command].feature`
|
|
184
185
|
|
|
185
186
|
```gherkin
|
|
186
|
-
@tui
|
|
187
187
|
Feature: [CLI Command]
|
|
188
188
|
As a user
|
|
189
189
|
I want to use the [command] CLI
|
|
@@ -192,7 +192,7 @@ Feature: [CLI Command]
|
|
|
192
192
|
|
|
193
193
|
### Step 2: Configure TUI in Fixtures
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
TUI is off in the scaffold. Uncomment `registerTuiSteps(test)` in `steps.ts`, the `tuiBdd` project in `playwright.config.ts`, and configure TUI in `fixtures.ts`:
|
|
196
196
|
|
|
197
197
|
```typescript
|
|
198
198
|
createTui: () => new TuiTesterAdapter({
|
|
@@ -224,14 +224,15 @@ Scenario: Navigate menu
|
|
|
224
224
|
|
|
225
225
|
See [TUI Patterns](references/tui-patterns.md) for more examples.
|
|
226
226
|
|
|
227
|
-
## Creating Hybrid Tests (
|
|
227
|
+
## Creating Hybrid Tests (API + UI)
|
|
228
|
+
|
|
229
|
+
A hybrid test is just a scenario that mixes API and UI steps. No tag or special project is needed.
|
|
228
230
|
|
|
229
231
|
### Step 1: Create Feature File
|
|
230
232
|
|
|
231
|
-
Location: `features/
|
|
233
|
+
Location: `features/ui/[workflow].feature` (or any folder a project reads)
|
|
232
234
|
|
|
233
235
|
```gherkin
|
|
234
|
-
@hybrid
|
|
235
236
|
Feature: [Workflow Name]
|
|
236
237
|
As a tester
|
|
237
238
|
I want to combine API and UI testing
|
|
@@ -336,21 +337,23 @@ And I store the value at "token" as "t"
|
|
|
336
337
|
After creating feature files:
|
|
337
338
|
|
|
338
339
|
```bash
|
|
339
|
-
#
|
|
340
|
-
|
|
340
|
+
# One-time: browser for UI tests
|
|
341
|
+
npx playwright install chromium
|
|
341
342
|
|
|
342
|
-
#
|
|
343
|
+
# Generate specs and run all tests (npm test runs bddgen first)
|
|
343
344
|
npm test
|
|
344
345
|
|
|
345
|
-
#
|
|
346
|
-
npx playwright test --project
|
|
347
|
-
npx playwright test --project
|
|
348
|
-
|
|
346
|
+
# Run one project (folder)
|
|
347
|
+
npx playwright test --project api
|
|
348
|
+
npx playwright test --project ui
|
|
349
|
+
|
|
350
|
+
# Run only scenarios with your own tag
|
|
351
|
+
TEST_TAGS=@smoke npm test
|
|
349
352
|
|
|
350
|
-
#
|
|
353
|
+
# Run specific feature (after npm run gen)
|
|
351
354
|
npx playwright test features/api/users.feature
|
|
352
355
|
|
|
353
|
-
#
|
|
356
|
+
# Debug mode
|
|
354
357
|
npx playwright test --debug
|
|
355
358
|
```
|
|
356
359
|
|
|
@@ -358,8 +361,10 @@ npx playwright test --debug
|
|
|
358
361
|
|
|
359
362
|
| Mistake | Solution |
|
|
360
363
|
|---------|----------|
|
|
361
|
-
| Forgot to run `npm run gen` |
|
|
362
|
-
|
|
|
364
|
+
| Forgot to run `npm run gen` | `npm test` does it; run it yourself before `npx playwright test` |
|
|
365
|
+
| Adding `@api`/`@ui`/`@hybrid` tags | Not needed; steps work everywhere, projects select by folder |
|
|
366
|
+
| Scenario never runs | Check the feature is in a folder a project reads |
|
|
367
|
+
| Step not found | Check exact wording in `katalyst-bdd-step-reference` (TUI: `I fill the TUI form:`) |
|
|
363
368
|
| Hardcoded test data | Use UUID generation for unique data |
|
|
364
369
|
| No cleanup registered | Always register cleanup for created resources |
|
|
365
370
|
| Scenarios depend on each other | Make each scenario independent |
|
|
@@ -7,7 +7,6 @@ Common patterns for API testing with the Katalyst BDD framework.
|
|
|
7
7
|
### List Resources
|
|
8
8
|
|
|
9
9
|
```gherkin
|
|
10
|
-
@api
|
|
11
10
|
Scenario: List all [resources]
|
|
12
11
|
Given I am authenticated as an admin via API
|
|
13
12
|
When I GET "/[endpoint]"
|
|
@@ -18,7 +17,6 @@ Scenario: List all [resources]
|
|
|
18
17
|
### Get Single Resource
|
|
19
18
|
|
|
20
19
|
```gherkin
|
|
21
|
-
@api
|
|
22
20
|
Scenario: Get [resource] by ID
|
|
23
21
|
Given I am authenticated as an admin via API
|
|
24
22
|
When I GET "/[endpoint]/1"
|
|
@@ -30,7 +28,6 @@ Scenario: Get [resource] by ID
|
|
|
30
28
|
### Create Resource
|
|
31
29
|
|
|
32
30
|
```gherkin
|
|
33
|
-
@api
|
|
34
31
|
Scenario: Create [resource]
|
|
35
32
|
Given I am authenticated as an admin via API
|
|
36
33
|
Given I generate a UUID and store as "runId"
|
|
@@ -50,7 +47,6 @@ Scenario: Create [resource]
|
|
|
50
47
|
### Update Resource (Full)
|
|
51
48
|
|
|
52
49
|
```gherkin
|
|
53
|
-
@api
|
|
54
50
|
Scenario: Update [resource] with PUT
|
|
55
51
|
Given I am authenticated as an admin via API
|
|
56
52
|
# First create the resource
|
|
@@ -75,7 +71,6 @@ Scenario: Update [resource] with PUT
|
|
|
75
71
|
### Update Resource (Partial)
|
|
76
72
|
|
|
77
73
|
```gherkin
|
|
78
|
-
@api
|
|
79
74
|
Scenario: Partial update with PATCH
|
|
80
75
|
Given I am authenticated as an admin via API
|
|
81
76
|
When I PATCH "/[endpoint]/{resourceId}" with JSON body:
|
|
@@ -89,7 +84,6 @@ Scenario: Partial update with PATCH
|
|
|
89
84
|
### Delete Resource
|
|
90
85
|
|
|
91
86
|
```gherkin
|
|
92
|
-
@api
|
|
93
87
|
Scenario: Delete [resource]
|
|
94
88
|
Given I am authenticated as an admin via API
|
|
95
89
|
# Create resource to delete
|
|
@@ -155,7 +149,6 @@ Scenario: Login and use token
|
|
|
155
149
|
### Not Found
|
|
156
150
|
|
|
157
151
|
```gherkin
|
|
158
|
-
@api
|
|
159
152
|
Scenario: Resource not found
|
|
160
153
|
Given I am authenticated as an admin via API
|
|
161
154
|
When I GET "/[endpoint]/99999"
|
|
@@ -165,7 +158,6 @@ Scenario: Resource not found
|
|
|
165
158
|
### Validation Error
|
|
166
159
|
|
|
167
160
|
```gherkin
|
|
168
|
-
@api
|
|
169
161
|
Scenario: Invalid data returns 400
|
|
170
162
|
Given I am authenticated as an admin via API
|
|
171
163
|
When I POST "/[endpoint]" with JSON body:
|
|
@@ -179,7 +171,6 @@ Scenario: Invalid data returns 400
|
|
|
179
171
|
### Unauthorized
|
|
180
172
|
|
|
181
173
|
```gherkin
|
|
182
|
-
@api
|
|
183
174
|
Scenario: Unauthorized access
|
|
184
175
|
# No authentication
|
|
185
176
|
When I GET "/admin/users"
|
|
@@ -189,7 +180,6 @@ Scenario: Unauthorized access
|
|
|
189
180
|
### Forbidden
|
|
190
181
|
|
|
191
182
|
```gherkin
|
|
192
|
-
@api
|
|
193
183
|
Scenario: User cannot access admin endpoint
|
|
194
184
|
Given I am authenticated as a user via API
|
|
195
185
|
When I GET "/admin/settings"
|
|
@@ -246,7 +236,6 @@ Then the value at "created_at" should match "^\d{4}-\d{2}-\d{2}"
|
|
|
246
236
|
### Pagination
|
|
247
237
|
|
|
248
238
|
```gherkin
|
|
249
|
-
@api
|
|
250
239
|
Scenario: Paginated list
|
|
251
240
|
Given I am authenticated as an admin via API
|
|
252
241
|
When I GET "/[endpoint]?page=1&limit=10"
|
|
@@ -260,7 +249,6 @@ Scenario: Paginated list
|
|
|
260
249
|
### Search/Filter
|
|
261
250
|
|
|
262
251
|
```gherkin
|
|
263
|
-
@api
|
|
264
252
|
Scenario: Filter by status
|
|
265
253
|
Given I am authenticated as an admin via API
|
|
266
254
|
When I GET "/[endpoint]?status=active"
|
|
@@ -271,7 +259,6 @@ Scenario: Filter by status
|
|
|
271
259
|
### Bulk Operations
|
|
272
260
|
|
|
273
261
|
```gherkin
|
|
274
|
-
@api
|
|
275
262
|
Scenario: Bulk create
|
|
276
263
|
Given I am authenticated as an admin via API
|
|
277
264
|
When I POST "/[endpoint]/bulk" with JSON body:
|
|
@@ -291,7 +278,6 @@ Scenario: Bulk create
|
|
|
291
278
|
### File Upload (Form Data)
|
|
292
279
|
|
|
293
280
|
```gherkin
|
|
294
|
-
@api
|
|
295
281
|
Scenario: Upload file
|
|
296
282
|
Given I am authenticated as an admin via API
|
|
297
283
|
Given I set header "Content-Type" to "multipart/form-data"
|
|
@@ -301,7 +287,6 @@ Scenario: Upload file
|
|
|
301
287
|
## Complete Example: User Management API
|
|
302
288
|
|
|
303
289
|
```gherkin
|
|
304
|
-
@api
|
|
305
290
|
Feature: User Management API
|
|
306
291
|
As an admin
|
|
307
292
|
I want to manage users via API
|
|
@@ -4,7 +4,7 @@ Common patterns for hybrid testing (combining API and UI) with the Katalyst BDD
|
|
|
4
4
|
|
|
5
5
|
## Core Principle
|
|
6
6
|
|
|
7
|
-
Hybrid tests
|
|
7
|
+
Hybrid tests are scenarios that mix API and UI steps. No tag is needed — every step works in any scenario. Put them in a folder a project reads (e.g. `features/ui/`). The typical flow:
|
|
8
8
|
1. **Setup** - Create test data via API (fast, reliable)
|
|
9
9
|
2. **Test** - Verify behavior in UI (user-facing validation)
|
|
10
10
|
3. **Cleanup** - Remove test data via API (automatic)
|
|
@@ -14,7 +14,6 @@ Hybrid tests use `@hybrid` tag to access both API and UI steps. The typical flow
|
|
|
14
14
|
### Create via API, Verify in UI
|
|
15
15
|
|
|
16
16
|
```gherkin
|
|
17
|
-
@hybrid
|
|
18
17
|
Scenario: Create user via API, verify in admin panel
|
|
19
18
|
# API: Create test data
|
|
20
19
|
Given I am authenticated as an admin via API
|
|
@@ -39,7 +38,6 @@ Scenario: Create user via API, verify in admin panel
|
|
|
39
38
|
### Setup Data, Test Workflow
|
|
40
39
|
|
|
41
40
|
```gherkin
|
|
42
|
-
@hybrid
|
|
43
41
|
Scenario: Test order workflow with pre-created product
|
|
44
42
|
# API: Create product
|
|
45
43
|
Given I am authenticated as an admin via API
|
|
@@ -67,7 +65,6 @@ Scenario: Test order workflow with pre-created product
|
|
|
67
65
|
### Verify API Changes Reflect in UI
|
|
68
66
|
|
|
69
67
|
```gherkin
|
|
70
|
-
@hybrid
|
|
71
68
|
Scenario: API update reflects in UI
|
|
72
69
|
# API: Create and update
|
|
73
70
|
Given I am authenticated as an admin via API
|
|
@@ -96,7 +93,6 @@ Scenario: API update reflects in UI
|
|
|
96
93
|
### Share IDs Between Layers
|
|
97
94
|
|
|
98
95
|
```gherkin
|
|
99
|
-
@hybrid
|
|
100
96
|
Scenario: Use API-created ID in UI navigation
|
|
101
97
|
# API: Create resource
|
|
102
98
|
Given I am authenticated as an admin via API
|
|
@@ -117,7 +113,6 @@ Scenario: Use API-created ID in UI navigation
|
|
|
117
113
|
### Share Data Between Layers
|
|
118
114
|
|
|
119
115
|
```gherkin
|
|
120
|
-
@hybrid
|
|
121
116
|
Scenario: Verify API data in UI
|
|
122
117
|
# Setup variables
|
|
123
118
|
Given I generate a UUID and store as "runId"
|
|
@@ -148,7 +143,6 @@ Scenario: Verify API data in UI
|
|
|
148
143
|
### Separate API and UI Auth
|
|
149
144
|
|
|
150
145
|
```gherkin
|
|
151
|
-
@hybrid
|
|
152
146
|
Scenario: Different auth for API vs UI
|
|
153
147
|
# API: Admin creates data
|
|
154
148
|
Given I am authenticated as an admin via API
|
|
@@ -169,7 +163,6 @@ Scenario: Different auth for API vs UI
|
|
|
169
163
|
### Use API Token in UI
|
|
170
164
|
|
|
171
165
|
```gherkin
|
|
172
|
-
@hybrid
|
|
173
166
|
Scenario: Get token from API, use in UI
|
|
174
167
|
# API: Login and get token
|
|
175
168
|
When I POST "/auth/login" with JSON body:
|
|
@@ -190,7 +183,6 @@ Scenario: Get token from API, use in UI
|
|
|
190
183
|
### Multi-Step Business Process
|
|
191
184
|
|
|
192
185
|
```gherkin
|
|
193
|
-
@hybrid
|
|
194
186
|
Scenario: Complete order processing workflow
|
|
195
187
|
# API: Setup - Create customer and product
|
|
196
188
|
Given I am authenticated as an admin via API
|
|
@@ -228,7 +220,6 @@ Scenario: Complete order processing workflow
|
|
|
228
220
|
### Data Synchronization Test
|
|
229
221
|
|
|
230
222
|
```gherkin
|
|
231
|
-
@hybrid
|
|
232
223
|
Scenario: Real-time sync between API and UI
|
|
233
224
|
Given I am authenticated as an admin via API
|
|
234
225
|
Given I generate a UUID and store as "runId"
|
|
@@ -264,7 +255,6 @@ Scenario: Real-time sync between API and UI
|
|
|
264
255
|
### Clean State Between Tests
|
|
265
256
|
|
|
266
257
|
```gherkin
|
|
267
|
-
@hybrid
|
|
268
258
|
Feature: User Settings
|
|
269
259
|
|
|
270
260
|
Background:
|
|
@@ -301,7 +291,6 @@ Feature: User Settings
|
|
|
301
291
|
### Seed Multiple Resources
|
|
302
292
|
|
|
303
293
|
```gherkin
|
|
304
|
-
@hybrid
|
|
305
294
|
Scenario: Dashboard with multiple data types
|
|
306
295
|
Given I am authenticated as an admin via API
|
|
307
296
|
Given I generate a UUID and store as "runId"
|
|
@@ -339,7 +328,6 @@ Scenario: Dashboard with multiple data types
|
|
|
339
328
|
### Test Error States
|
|
340
329
|
|
|
341
330
|
```gherkin
|
|
342
|
-
@hybrid
|
|
343
331
|
Scenario: UI shows error when API resource deleted
|
|
344
332
|
# API: Create and immediately delete
|
|
345
333
|
Given I am authenticated as an admin via API
|
|
@@ -361,7 +349,6 @@ Scenario: UI shows error when API resource deleted
|
|
|
361
349
|
## Complete Example: User Onboarding Flow
|
|
362
350
|
|
|
363
351
|
```gherkin
|
|
364
|
-
@hybrid
|
|
365
352
|
Feature: User Onboarding
|
|
366
353
|
As a product owner
|
|
367
354
|
I want to test the complete onboarding flow
|