playwright-cucumber-ts-steps 1.1.7 → 1.1.8
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/dist/backend/actions/click.d.ts +2 -0
- package/dist/backend/actions/click.d.ts.map +1 -0
- package/dist/backend/actions/click.js +179 -0
- package/dist/backend/actions/find.d.ts +2 -0
- package/dist/backend/actions/find.d.ts.map +1 -0
- package/dist/backend/actions/find.js +291 -0
- package/dist/backend/actions/form.d.ts +2 -0
- package/dist/backend/actions/form.d.ts.map +1 -0
- package/dist/backend/actions/form.js +185 -0
- package/dist/backend/actions/formTable.js +1 -1
- package/dist/backend/actions/frames.d.ts +2 -0
- package/dist/backend/actions/frames.d.ts.map +1 -0
- package/dist/backend/actions/frames.js +60 -0
- package/dist/backend/actions/index.d.ts +10 -0
- package/dist/backend/actions/index.d.ts.map +1 -1
- package/dist/backend/actions/index.js +10 -0
- package/dist/backend/actions/inputs.d.ts +2 -0
- package/dist/backend/actions/inputs.d.ts.map +1 -0
- package/dist/backend/actions/inputs.js +177 -0
- package/dist/backend/actions/keyboard.d.ts +2 -0
- package/dist/backend/actions/keyboard.d.ts.map +1 -0
- package/dist/backend/actions/keyboard.js +62 -0
- package/dist/backend/actions/misc.d.ts +2 -0
- package/dist/backend/actions/misc.d.ts.map +1 -0
- package/dist/backend/actions/misc.js +144 -0
- package/dist/backend/actions/mobile.d.ts +2 -0
- package/dist/backend/actions/mobile.d.ts.map +1 -0
- package/dist/backend/actions/mobile.js +87 -0
- package/dist/backend/actions/mouse.d.ts +2 -0
- package/dist/backend/actions/mouse.d.ts.map +1 -0
- package/dist/backend/actions/mouse.js +105 -0
- package/dist/backend/actions/navigation.js +31 -7
- package/dist/backend/actions/waits.d.ts +2 -0
- package/dist/backend/actions/waits.d.ts.map +1 -0
- package/dist/backend/actions/waits.js +51 -0
- package/dist/backend/api/index.d.ts +1 -0
- package/dist/backend/api/index.d.ts.map +1 -1
- package/dist/backend/api/index.js +1 -0
- package/dist/backend/api/network.d.ts +2 -0
- package/dist/backend/api/network.d.ts.map +1 -0
- package/dist/backend/api/network.js +145 -0
- package/dist/backend/assertions/pageState.js +25 -14
- package/dist/backend/assertions/visibility.js +116 -12
- package/dist/backend/utils/state.d.ts +18 -0
- package/dist/backend/utils/state.d.ts.map +1 -0
- package/dist/backend/utils/state.js +84 -0
- package/dist/core/registry.d.ts +14 -14
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +13 -4
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +91 -37
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setActiveElement = setActiveElement;
|
|
4
|
+
exports.getActiveElement = getActiveElement;
|
|
5
|
+
exports.setActiveElements = setActiveElements;
|
|
6
|
+
exports.getActiveElements = getActiveElements;
|
|
7
|
+
exports.setVariable = setVariable;
|
|
8
|
+
exports.getVariable = getVariable;
|
|
9
|
+
exports.parseClickOptions = parseClickOptions;
|
|
10
|
+
// 1. STATE MANAGEMENT
|
|
11
|
+
// We attach data to the Playwright Page object so it persists between steps.
|
|
12
|
+
function setActiveElement(page, element) {
|
|
13
|
+
page.__bdd_element = element;
|
|
14
|
+
}
|
|
15
|
+
function getActiveElement(page) {
|
|
16
|
+
const el = page.__bdd_element;
|
|
17
|
+
if (!el) {
|
|
18
|
+
throw new Error("❌ No stored element found. Did you forget a 'When I find...' step?");
|
|
19
|
+
}
|
|
20
|
+
return el;
|
|
21
|
+
}
|
|
22
|
+
function setActiveElements(page, elements) {
|
|
23
|
+
page.__bdd_elements = elements;
|
|
24
|
+
}
|
|
25
|
+
function getActiveElements(page) {
|
|
26
|
+
const els = page.__bdd_elements;
|
|
27
|
+
if (!els) {
|
|
28
|
+
throw new Error("❌ No stored elements list found.");
|
|
29
|
+
}
|
|
30
|
+
return els;
|
|
31
|
+
}
|
|
32
|
+
// 2. DATA / ALIAS MANAGEMENT (for @variable support)
|
|
33
|
+
function setVariable(page, key, value) {
|
|
34
|
+
if (!page.__bdd_data) {
|
|
35
|
+
page.__bdd_data = {};
|
|
36
|
+
}
|
|
37
|
+
page.__bdd_data[key] = value;
|
|
38
|
+
}
|
|
39
|
+
function getVariable(page, key) {
|
|
40
|
+
const data = page.__bdd_data;
|
|
41
|
+
return data ? data[key] : undefined;
|
|
42
|
+
}
|
|
43
|
+
// 3. OPTION PARSERS
|
|
44
|
+
// Converts Gherkin DataTables into Playwright ClickOptions
|
|
45
|
+
function parseClickOptions(table) {
|
|
46
|
+
if (!table)
|
|
47
|
+
return {};
|
|
48
|
+
let hash = {};
|
|
49
|
+
// Handle Cucumber DataTable object (legacy) or raw Array
|
|
50
|
+
if (typeof table.rowsHash === "function") {
|
|
51
|
+
hash = table.rowsHash();
|
|
52
|
+
}
|
|
53
|
+
else if (Array.isArray(table)) {
|
|
54
|
+
// Convert Array of Arrays [['force', 'true']] to Object { force: 'true' }
|
|
55
|
+
table.forEach((row) => {
|
|
56
|
+
if (Array.isArray(row) && row.length >= 2) {
|
|
57
|
+
hash[row[0].toString()] = row[1].toString();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
const options = {};
|
|
65
|
+
// Parse specific boolean/number values
|
|
66
|
+
if (hash["force"] === "true")
|
|
67
|
+
options.force = true;
|
|
68
|
+
if (hash["button"])
|
|
69
|
+
options.button = hash["button"];
|
|
70
|
+
if (hash["timeout"])
|
|
71
|
+
options.timeout = parseInt(hash["timeout"], 10);
|
|
72
|
+
// Handle modifiers (comma separated)
|
|
73
|
+
if (hash["modifiers"]) {
|
|
74
|
+
options.modifiers = hash["modifiers"].split(",").map((m) => m.trim());
|
|
75
|
+
}
|
|
76
|
+
// Handle position (x,y)
|
|
77
|
+
if (hash["x"] && hash["y"]) {
|
|
78
|
+
options.position = {
|
|
79
|
+
x: parseInt(hash["x"], 10),
|
|
80
|
+
y: parseInt(hash["y"], 10),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return options;
|
|
84
|
+
}
|
package/dist/core/registry.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { CucumberExpression } from "@cucumber/cucumber-expressions";
|
|
2
2
|
import { Page } from "@playwright/test";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @param fn - The async function to execute. It receives the Playwright Page object as the first argument.
|
|
7
|
-
* * @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* Step('I scroll to bottom', async (page) => {
|
|
10
|
-
* await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
|
11
|
-
* });
|
|
12
|
-
* ```
|
|
4
|
+
* Define the type of function for our steps.
|
|
5
|
+
* Every step automatically gets 'page' as the first argument.
|
|
13
6
|
*/
|
|
14
7
|
export type StepAction = (page: Page, ...args: any[]) => Promise<void>;
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
/**
|
|
9
|
+
* 1. StepDefinition Interface
|
|
10
|
+
* Updated to allow both CucumberExpression (legacy) AND RegExp (standard)
|
|
11
|
+
*/
|
|
12
|
+
export interface StepDefinition {
|
|
13
|
+
expression: CucumberExpression | RegExp;
|
|
17
14
|
fn: StepAction;
|
|
18
|
-
pattern: string;
|
|
15
|
+
pattern: string | RegExp;
|
|
19
16
|
}
|
|
20
17
|
export declare const stepRegistry: StepDefinition[];
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* 3. The Function to Register Steps
|
|
20
|
+
* Supports passing a string (converted to CucumberExpression) OR a direct RegExp.
|
|
21
|
+
*/
|
|
22
|
+
export declare function Step(pattern: string | RegExp, fn: StepAction): void;
|
|
23
23
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAEnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAEnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAAC;IACxC,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAGD,eAAO,MAAM,YAAY,EAAE,cAAc,EAAO,CAAC;AAIjD;;;GAGG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,EAAE,UAAU,QAgB5D"}
|
package/dist/core/registry.js
CHANGED
|
@@ -5,13 +5,22 @@ exports.Step = Step;
|
|
|
5
5
|
// src/core/registry.ts
|
|
6
6
|
const cucumber_expressions_1 = require("@cucumber/cucumber-expressions");
|
|
7
7
|
// 2. The Global Registry
|
|
8
|
-
// This array stores every step you create in the backend folder
|
|
9
8
|
exports.stepRegistry = [];
|
|
10
9
|
const parameterTypeRegistry = new cucumber_expressions_1.ParameterTypeRegistry();
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* 3. The Function to Register Steps
|
|
12
|
+
* Supports passing a string (converted to CucumberExpression) OR a direct RegExp.
|
|
13
|
+
*/
|
|
13
14
|
function Step(pattern, fn) {
|
|
14
|
-
|
|
15
|
+
let expression;
|
|
16
|
+
if (pattern instanceof RegExp) {
|
|
17
|
+
// ✅ If it's a Regex, use it directly (Faster, Standard)
|
|
18
|
+
expression = pattern;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// ⚠️ If it's a String, convert to Cucumber Expression (Legacy)
|
|
22
|
+
expression = new cucumber_expressions_1.CucumberExpression(pattern, parameterTypeRegistry);
|
|
23
|
+
}
|
|
15
24
|
exports.stepRegistry.push({
|
|
16
25
|
expression,
|
|
17
26
|
fn,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAMA,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;
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/core/runner.ts"],"names":[],"mappings":"AAMA,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;AASD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,QA6LpE"}
|
package/dist/core/runner.js
CHANGED
|
@@ -58,7 +58,6 @@ function runTests(featureGlob, options) {
|
|
|
58
58
|
for (const file of files) {
|
|
59
59
|
const content = fs.readFileSync(file, "utf8");
|
|
60
60
|
// 1. CAPTURE FEATURE TAGS
|
|
61
|
-
// Loose Regex: Matches any lines starting with @ above "Feature:"
|
|
62
61
|
const featureTagMatch = content.match(/((?:@\S+\s*)+)Feature:/);
|
|
63
62
|
const rawFeatureTags = featureTagMatch ? featureTagMatch[1] : "";
|
|
64
63
|
const featureTags = rawFeatureTags.replace(/[\r\n]+/g, " ").trim();
|
|
@@ -67,9 +66,8 @@ function runTests(featureGlob, options) {
|
|
|
67
66
|
? featureMatch[1].trim()
|
|
68
67
|
: "Unnamed Feature";
|
|
69
68
|
test_1.test.describe(featureName, () => {
|
|
70
|
-
// 2.
|
|
69
|
+
// 2. SCENARIO REGEX
|
|
71
70
|
// Matches: Optional Tags -> (Scenario OR Scenario Outline) -> Name
|
|
72
|
-
// Change: @\S+ allows dots/dashes. "Scenario|Scenario Outline" supports outlines.
|
|
73
71
|
const scenarioRegex = /(?:((?:@\S+\s*)+))?(?:Scenario|Scenario Outline):\s*(.+)/g;
|
|
74
72
|
let match;
|
|
75
73
|
let foundCount = 0;
|
|
@@ -83,9 +81,7 @@ function runTests(featureGlob, options) {
|
|
|
83
81
|
const fullName = combinedTags
|
|
84
82
|
? `${scenarioName} ${combinedTags}`
|
|
85
83
|
: scenarioName;
|
|
86
|
-
//
|
|
87
|
-
// console.log(` 👉 Found: "${scenarioName}" [Tags: ${combinedTags}]`);
|
|
88
|
-
// 4. ENV FILTERING (Optional)
|
|
84
|
+
// 4. ENV FILTERING
|
|
89
85
|
const activeFilter = options?.tags || envTag;
|
|
90
86
|
if (activeFilter) {
|
|
91
87
|
const targetGroups = activeFilter.split(",").map((t) => t.trim());
|
|
@@ -96,6 +92,7 @@ function runTests(featureGlob, options) {
|
|
|
96
92
|
if (!isMatch)
|
|
97
93
|
continue;
|
|
98
94
|
}
|
|
95
|
+
// 5. EXTRACT SCENARIO BLOCK
|
|
99
96
|
const startIndex = match.index + match[0].length;
|
|
100
97
|
const nextMatchIndex = content
|
|
101
98
|
.slice(startIndex)
|
|
@@ -103,43 +100,91 @@ function runTests(featureGlob, options) {
|
|
|
103
100
|
const blockEnd = nextMatchIndex === -1 ? content.length : startIndex + nextMatchIndex;
|
|
104
101
|
const scenarioBlock = content.slice(startIndex, blockEnd);
|
|
105
102
|
(0, test_1.test)(fullName, async ({ page }, testInfo) => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
103
|
+
// ==================================================
|
|
104
|
+
// PHASE 1: PARSE GHERKIN (Preserve Formatting)
|
|
105
|
+
// ==================================================
|
|
106
|
+
const rawLines = scenarioBlock.split("\n");
|
|
107
|
+
const steps = [];
|
|
108
|
+
let currentStep = null;
|
|
109
|
+
let docStringBuffer = [];
|
|
110
|
+
let isDocStringOpen = false;
|
|
111
|
+
for (let line of rawLines) {
|
|
112
|
+
const trimmedLine = line.trim();
|
|
113
|
+
// A. Handle DocStrings (""")
|
|
114
|
+
if (trimmedLine.startsWith('"""')) {
|
|
115
|
+
isDocStringOpen = !isDocStringOpen;
|
|
116
|
+
if (!isDocStringOpen && currentStep) {
|
|
117
|
+
// Closing DocString: Save buffer to step
|
|
118
|
+
currentStep.docString = docStringBuffer.join("\n");
|
|
119
|
+
docStringBuffer = [];
|
|
120
|
+
}
|
|
116
121
|
continue;
|
|
117
|
-
// Handle Data Tables
|
|
118
|
-
const tableData = [];
|
|
119
|
-
while (i + 1 < lines.length && lines[i + 1].startsWith("|")) {
|
|
120
|
-
i++;
|
|
121
|
-
const row = lines[i]
|
|
122
|
-
.split("|")
|
|
123
|
-
.map((cell) => cell.trim())
|
|
124
|
-
.filter((cell) => cell !== "");
|
|
125
|
-
tableData.push(row);
|
|
126
122
|
}
|
|
127
|
-
|
|
123
|
+
// B. Inside DocString? Capture raw line (preserve indent)
|
|
124
|
+
if (isDocStringOpen) {
|
|
125
|
+
docStringBuffer.push(line); // Don't trim!
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// C. Skip Empty Lines & Comments
|
|
129
|
+
if (!trimmedLine ||
|
|
130
|
+
trimmedLine.startsWith("#") ||
|
|
131
|
+
trimmedLine.startsWith("@")) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
// D. Handle Data Tables (| col | col |)
|
|
135
|
+
if (trimmedLine.startsWith("|")) {
|
|
136
|
+
if (currentStep) {
|
|
137
|
+
if (!currentStep.dataTable)
|
|
138
|
+
currentStep.dataTable = [];
|
|
139
|
+
const row = trimmedLine
|
|
140
|
+
.split("|")
|
|
141
|
+
.map((cell) => cell.trim())
|
|
142
|
+
.filter((cell, index, arr) => index > 0 && index < arr.length - 1);
|
|
143
|
+
// Simple split often leaves empty strings at start/end
|
|
144
|
+
// Better split logic:
|
|
145
|
+
const cleanRow = trimmedLine
|
|
146
|
+
.split("|")
|
|
147
|
+
.slice(1, -1) // Remove first and last empty splits from |...|
|
|
148
|
+
.map((c) => c.trim());
|
|
149
|
+
currentStep.dataTable.push(cleanRow);
|
|
150
|
+
}
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// E. It is a New Step
|
|
154
|
+
const cleanText = trimmedLine
|
|
128
155
|
.replace(/^(Given|When|Then|And|But)\s+/i, "")
|
|
129
|
-
.replace(/:$/, "")
|
|
156
|
+
.replace(/:$/, "") // Remove trailing colon
|
|
130
157
|
.trim();
|
|
131
|
-
|
|
158
|
+
currentStep = {
|
|
159
|
+
text: trimmedLine,
|
|
160
|
+
cleanText: cleanText,
|
|
161
|
+
};
|
|
162
|
+
steps.push(currentStep);
|
|
163
|
+
}
|
|
164
|
+
// ==================================================
|
|
165
|
+
// PHASE 2: EXECUTE STEPS
|
|
166
|
+
// ==================================================
|
|
167
|
+
console.log(`\n🔹 Scenario: ${scenarioName}`);
|
|
168
|
+
for (const step of steps) {
|
|
169
|
+
const matchResult = findMatchingStep(step.cleanText);
|
|
132
170
|
if (!matchResult) {
|
|
133
|
-
throw new Error(`❌ Undefined Step: "${
|
|
171
|
+
throw new Error(`❌ Undefined Step: "${step.cleanText}"`);
|
|
134
172
|
}
|
|
135
173
|
try {
|
|
174
|
+
console.log(` executing: ${step.text.trim()}`);
|
|
136
175
|
const args = [...matchResult.args];
|
|
137
|
-
|
|
138
|
-
|
|
176
|
+
// Append Data Table if present
|
|
177
|
+
if (step.dataTable && step.dataTable.length > 0) {
|
|
178
|
+
args.push(step.dataTable);
|
|
179
|
+
}
|
|
180
|
+
// Append DocString if present
|
|
181
|
+
if (step.docString) {
|
|
182
|
+
args.push(step.docString);
|
|
183
|
+
}
|
|
139
184
|
await matchResult.fn(page, ...args);
|
|
140
185
|
}
|
|
141
186
|
catch (error) {
|
|
142
|
-
console.error(`❌ Failed at step: "${
|
|
187
|
+
console.error(`❌ Failed at step: "${step.text.trim()}"`);
|
|
143
188
|
const screenshot = await page.screenshot({
|
|
144
189
|
fullPage: true,
|
|
145
190
|
type: "png",
|
|
@@ -153,32 +198,41 @@ function runTests(featureGlob, options) {
|
|
|
153
198
|
}
|
|
154
199
|
});
|
|
155
200
|
}
|
|
156
|
-
// SAFETY CHECK
|
|
157
201
|
if (foundCount === 0) {
|
|
158
202
|
console.warn(`⚠️ File matched but 0 Scenarios found in: ${file}`);
|
|
159
|
-
console.warn(` Check if you are using 'Scenario Outline' or strange spacing.`);
|
|
160
203
|
}
|
|
161
204
|
});
|
|
162
205
|
}
|
|
163
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Finds the matching step definition from the registry.
|
|
209
|
+
* Supports: RegExp (with capture groups) and CucumberExpressions.
|
|
210
|
+
*/
|
|
164
211
|
function findMatchingStep(text) {
|
|
165
212
|
for (const step of registry_1.stepRegistry) {
|
|
213
|
+
// 1. RegExp Match
|
|
166
214
|
if (step.expression instanceof RegExp) {
|
|
167
215
|
const match = step.expression.exec(text);
|
|
168
|
-
if (match)
|
|
216
|
+
if (match) {
|
|
217
|
+
// match[0] is full string, slice(1) are capture groups
|
|
169
218
|
return { fn: step.fn, args: match.slice(1) };
|
|
219
|
+
}
|
|
170
220
|
}
|
|
221
|
+
// 2. Cucumber Expression Match (if strictly typed)
|
|
171
222
|
else if (typeof step.expression.match === "function") {
|
|
172
223
|
const match = step.expression.match(text);
|
|
173
|
-
if (match)
|
|
224
|
+
if (match) {
|
|
174
225
|
return {
|
|
175
226
|
fn: step.fn,
|
|
176
227
|
args: match.map((arg) => arg.getValue(null)),
|
|
177
228
|
};
|
|
229
|
+
}
|
|
178
230
|
}
|
|
231
|
+
// 3. String Match (Legacy/Simple)
|
|
179
232
|
else if (typeof step.expression === "string") {
|
|
180
|
-
if (step.expression === text)
|
|
233
|
+
if (step.expression === text) {
|
|
181
234
|
return { fn: step.fn, args: [] };
|
|
235
|
+
}
|
|
182
236
|
}
|
|
183
237
|
}
|
|
184
238
|
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.8",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|