playwright-cucumber-ts-steps 1.1.1 → 1.1.3
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 +22 -13
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +26 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,30 +95,39 @@ Feature: User Authentication
|
|
|
95
95
|
### 4. Run Tests
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
|
-
npx playwright test
|
|
98
|
+
npx playwright test
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
---
|
|
102
102
|
|
|
103
|
-
## 🏷️
|
|
103
|
+
## 🏷️ Tag Filtering (New!)
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
We support a **Friendly Syntax** for filtering tests via the `TAGS` environment variable.
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
| Logic | Symbol | Example | Description |
|
|
108
|
+
| ------- | ------- | ---------------- | ----------------------------------------------------- |
|
|
109
|
+
| **OR** | `,` | `@login,@signup` | Run tests that have `@login` **OR** `@signup`. |
|
|
110
|
+
| **AND** | `+` | `@smoke+@api` | Run tests that have **BOTH** `@smoke` **AND** `@api`. |
|
|
111
|
+
| **MIX** | `,` `+` | `@a+@b, @c` | Run tests with (`@a` AND `@b`) **OR** just `@c`. |
|
|
108
112
|
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
**Usage:**
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# Run only smoke tests
|
|
117
|
+
TAGS='@smoke' npx playwright test
|
|
111
118
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
...
|
|
119
|
+
# Run smoke tests that are also critical
|
|
120
|
+
TAGS='@smoke+@critical' npx playwright test
|
|
115
121
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
...
|
|
122
|
+
# Run login OR regression tests
|
|
123
|
+
TAGS='@login,@regression' npx playwright test
|
|
119
124
|
|
|
120
125
|
```
|
|
121
126
|
|
|
127
|
+
_(On Windows PowerShell, use `$env:TAGS="@smoke"; npx playwright test`)_
|
|
128
|
+
|
|
129
|
+
````
|
|
130
|
+
|
|
122
131
|
**In your Test Runner (`tests/bdd.spec.ts`):**
|
|
123
132
|
|
|
124
133
|
```typescript
|
|
@@ -129,7 +138,7 @@ import { runTests } from "playwright-cucumber-ts-steps";
|
|
|
129
138
|
|
|
130
139
|
// OPTION 2: Run only Smoke tests
|
|
131
140
|
runTests("features/*.feature", { tags: "@smoke" });
|
|
132
|
-
|
|
141
|
+
````
|
|
133
142
|
|
|
134
143
|
---
|
|
135
144
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAOA,OAAO,0BAA0B,CAAC;AAClC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,uBAAuB,CAAC;AAE/B,OAAO,qBAAqB,CAAC;AAE7B,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC3C;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,QAqHpE"}
|
package/dist/core/runner.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.runTests = runTests;
|
|
37
|
+
// src/core/runner.ts
|
|
37
38
|
const test_1 = require("@playwright/test");
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const glob_1 = require("glob");
|
|
@@ -51,6 +52,7 @@ function runTests(featureGlob, options) {
|
|
|
51
52
|
state_1.dbState.setAdapter(options.dbQuery);
|
|
52
53
|
}
|
|
53
54
|
const files = (0, glob_1.globSync)(featureGlob);
|
|
55
|
+
const envTag = process.env.TAGS;
|
|
54
56
|
if (files.length === 0) {
|
|
55
57
|
console.warn(`⚠️ No feature files found for pattern: ${featureGlob}`);
|
|
56
58
|
}
|
|
@@ -61,20 +63,36 @@ function runTests(featureGlob, options) {
|
|
|
61
63
|
? featureMatch[1].trim()
|
|
62
64
|
: "Unnamed Feature";
|
|
63
65
|
test_1.test.describe(featureName, () => {
|
|
64
|
-
// 1. SAFE SCENARIO REGEX
|
|
65
66
|
const scenarioRegex = /(?:(@[^:\r\n]+)\s+)?Scenario:\s*(.+)/g;
|
|
66
67
|
let match;
|
|
67
68
|
while ((match = scenarioRegex.exec(content)) !== null) {
|
|
68
69
|
const foundTags = match[1] || "";
|
|
69
70
|
const scenarioName = match[2].trim();
|
|
71
|
+
// 1. APPEND TAGS TO TITLE (Keeps -g working if needed)
|
|
72
|
+
const fullName = foundTags
|
|
73
|
+
? `${scenarioName} ${foundTags}`
|
|
74
|
+
: scenarioName;
|
|
75
|
+
// 2. 🔥 FRIENDLY TAG FILTERING 🔥
|
|
76
|
+
const activeFilter = options?.tags || envTag;
|
|
77
|
+
if (activeFilter) {
|
|
78
|
+
// Logic:
|
|
79
|
+
// ',' = OR (e.g., "@login, @smoke")
|
|
80
|
+
// '+' = AND (e.g., "@login+@smoke")
|
|
81
|
+
const orGroups = activeFilter.split(","); // Split into OR groups
|
|
82
|
+
const isMatch = orGroups.some((group) => {
|
|
83
|
+
// For each group, check if ALL tags (joined by +) are present
|
|
84
|
+
const andTags = group.split("+").map((t) => t.trim());
|
|
85
|
+
return andTags.every((t) => foundTags.includes(t));
|
|
86
|
+
});
|
|
87
|
+
if (!isMatch) {
|
|
88
|
+
continue; // Skip if no groups matched
|
|
89
|
+
}
|
|
90
|
+
}
|
|
70
91
|
const startIndex = match.index + match[0].length;
|
|
71
92
|
const nextMatchIndex = content.slice(startIndex).search(/Scenario:/);
|
|
72
93
|
const blockEnd = nextMatchIndex === -1 ? content.length : startIndex + nextMatchIndex;
|
|
73
94
|
const scenarioBlock = content.slice(startIndex, blockEnd);
|
|
74
|
-
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
(0, test_1.test)(scenarioName, async ({ page }, testInfo) => {
|
|
95
|
+
(0, test_1.test)(fullName, async ({ page }, testInfo) => {
|
|
78
96
|
const lines = scenarioBlock
|
|
79
97
|
.trim()
|
|
80
98
|
.split("\n")
|
|
@@ -86,7 +104,6 @@ function runTests(featureGlob, options) {
|
|
|
86
104
|
stepText.startsWith("@") ||
|
|
87
105
|
stepText === "")
|
|
88
106
|
continue;
|
|
89
|
-
// Handle Data Tables
|
|
90
107
|
const tableData = [];
|
|
91
108
|
while (i + 1 < lines.length && lines[i + 1].startsWith("|")) {
|
|
92
109
|
i++;
|
|
@@ -100,7 +117,6 @@ function runTests(featureGlob, options) {
|
|
|
100
117
|
.replace(/^(Given|When|Then|And|But)\s+/i, "")
|
|
101
118
|
.replace(/:$/, "")
|
|
102
119
|
.trim();
|
|
103
|
-
// 2. SMART STEP MATCHING
|
|
104
120
|
const matchResult = findMatchingStep(cleanStep);
|
|
105
121
|
if (!matchResult) {
|
|
106
122
|
throw new Error(`❌ Undefined Step: "${cleanStep}"`);
|
|
@@ -109,7 +125,6 @@ function runTests(featureGlob, options) {
|
|
|
109
125
|
const args = [...matchResult.args];
|
|
110
126
|
if (tableData.length > 0)
|
|
111
127
|
args.push(tableData);
|
|
112
|
-
console.log(`✅ Executing: ${cleanStep}`);
|
|
113
128
|
await matchResult.fn(page, ...args);
|
|
114
129
|
}
|
|
115
130
|
catch (error) {
|
|
@@ -130,32 +145,24 @@ function runTests(featureGlob, options) {
|
|
|
130
145
|
});
|
|
131
146
|
}
|
|
132
147
|
}
|
|
133
|
-
// 3. ROBUST FINDER FUNCTION
|
|
134
148
|
function findMatchingStep(text) {
|
|
135
149
|
for (const step of registry_1.stepRegistry) {
|
|
136
|
-
// A. Handle RegExp (If you defined steps with Regex)
|
|
137
150
|
if (step.expression instanceof RegExp) {
|
|
138
151
|
const match = step.expression.exec(text);
|
|
139
|
-
if (match)
|
|
152
|
+
if (match)
|
|
140
153
|
return { fn: step.fn, args: match.slice(1) };
|
|
141
|
-
}
|
|
142
154
|
}
|
|
143
|
-
// B. Handle Cucumber Expressions (The Objects we saw in your logs)
|
|
144
|
-
// We check if it has a .match() method
|
|
145
155
|
else if (typeof step.expression.match === "function") {
|
|
146
156
|
const match = step.expression.match(text);
|
|
147
|
-
if (match)
|
|
157
|
+
if (match)
|
|
148
158
|
return {
|
|
149
159
|
fn: step.fn,
|
|
150
160
|
args: match.map((arg) => arg.getValue(null)),
|
|
151
161
|
};
|
|
152
|
-
}
|
|
153
162
|
}
|
|
154
|
-
// C. Handle Simple Strings
|
|
155
163
|
else if (typeof step.expression === "string") {
|
|
156
|
-
if (step.expression === text)
|
|
164
|
+
if (step.expression === text)
|
|
157
165
|
return { fn: step.fn, args: [] };
|
|
158
|
-
}
|
|
159
166
|
}
|
|
160
167
|
}
|
|
161
168
|
return null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright-cucumber-ts-steps",
|
|
3
3
|
"description": "A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|