playwright-cucumber-ts-steps 1.3.0 ā 1.3.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/dist/backend/actions/click.d.ts +84 -0
- package/dist/backend/actions/click.d.ts.map +1 -1
- package/dist/backend/actions/click.js +167 -17
- package/dist/backend/actions/form.d.ts +6 -0
- package/dist/backend/actions/form.d.ts.map +1 -1
- package/dist/backend/actions/form.js +17 -1
- package/dist/backend/actions/formTable.js +1 -1
- package/dist/backend/actions/frames.js +3 -3
- package/dist/backend/actions/index.d.ts +2 -0
- package/dist/backend/actions/index.d.ts.map +1 -1
- package/dist/backend/actions/index.js +2 -0
- package/dist/backend/actions/inputs.js +18 -18
- package/dist/backend/actions/interactions.d.ts +14 -5
- package/dist/backend/actions/interactions.d.ts.map +1 -1
- package/dist/backend/actions/interactions.js +69 -13
- package/dist/backend/actions/keyboard.js +6 -6
- package/dist/backend/actions/misc.d.ts +8 -2
- package/dist/backend/actions/misc.d.ts.map +1 -1
- package/dist/backend/actions/misc.js +64 -16
- package/dist/backend/actions/mobile.js +7 -7
- package/dist/backend/actions/mouse.js +9 -9
- package/dist/backend/actions/navigation.js +5 -5
- package/dist/backend/actions/visual.d.ts +47 -0
- package/dist/backend/actions/visual.d.ts.map +1 -0
- package/dist/backend/actions/visual.js +97 -0
- package/dist/backend/actions/waits.d.ts +6 -0
- package/dist/backend/actions/waits.d.ts.map +1 -1
- package/dist/backend/actions/waits.js +18 -5
- package/dist/backend/api/assertions.js +3 -3
- package/dist/backend/api/mock.js +3 -3
- package/dist/backend/api/network.js +6 -6
- package/dist/backend/api/requests.js +4 -4
- package/dist/backend/assertions/document.d.ts +61 -0
- package/dist/backend/assertions/document.d.ts.map +1 -0
- package/dist/backend/assertions/document.js +166 -0
- package/dist/backend/assertions/elements.d.ts +163 -0
- package/dist/backend/assertions/elements.d.ts.map +1 -0
- package/dist/backend/assertions/elements.js +441 -0
- package/dist/backend/assertions/expectVisible.js +1 -1
- package/dist/backend/assertions/forms.d.ts +43 -0
- package/dist/backend/assertions/forms.d.ts.map +1 -0
- package/dist/backend/assertions/forms.js +126 -0
- package/dist/backend/assertions/index.d.ts +10 -0
- package/dist/backend/assertions/index.d.ts.map +1 -1
- package/dist/backend/assertions/index.js +10 -0
- package/dist/backend/assertions/pageState.js +4 -4
- package/dist/backend/assertions/storage.d.ts +67 -0
- package/dist/backend/assertions/storage.d.ts.map +1 -0
- package/dist/backend/assertions/storage.js +220 -0
- package/dist/backend/assertions/text.d.ts +103 -12
- package/dist/backend/assertions/text.d.ts.map +1 -1
- package/dist/backend/assertions/text.js +207 -28
- package/dist/backend/assertions/visibility.d.ts +18 -0
- package/dist/backend/assertions/visibility.d.ts.map +1 -1
- package/dist/backend/assertions/visibility.js +58 -12
- package/dist/backend/auth/index.js +2 -2
- package/dist/backend/db/steps.d.ts +2 -2
- package/dist/backend/db/steps.d.ts.map +1 -1
- package/dist/backend/db/steps.js +11 -11
- package/dist/backend/elements/alerts.js +3 -3
- package/dist/backend/elements/find.js +26 -24
- package/dist/backend/elements/forms.js +4 -4
- package/dist/backend/elements/frames.js +3 -3
- package/dist/backend/utils/fixtures.js +1 -1
- package/dist/backend/utils/resolver.d.ts +6 -0
- package/dist/backend/utils/resolver.d.ts.map +1 -0
- package/dist/backend/utils/resolver.js +19 -0
- package/dist/component/index.d.ts +3 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +6 -0
- package/dist/component/runner.d.ts +18 -0
- package/dist/component/runner.d.ts.map +1 -0
- package/dist/component/runner.js +91 -0
- package/dist/core/runner.d.ts +1 -0
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +179 -124
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/metadata.json +564 -172
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/component/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7C,YAAY,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runComponentTests = void 0;
|
|
4
|
+
// src/component/index.ts
|
|
5
|
+
var runner_1 = require("./runner");
|
|
6
|
+
Object.defineProperty(exports, "runComponentTests", { enumerable: true, get: function () { return runner_1.runComponentTests; } });
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "../backend/actions/index";
|
|
2
|
+
import "../backend/assertions/index";
|
|
3
|
+
import "../backend/elements/index";
|
|
4
|
+
import "../backend/api/index";
|
|
5
|
+
import "../backend/auth/index";
|
|
6
|
+
import "../backend/utils/state";
|
|
7
|
+
import "../backend/db/index";
|
|
8
|
+
export interface ComponentRunnerOptions {
|
|
9
|
+
tags?: string;
|
|
10
|
+
mountDir?: string;
|
|
11
|
+
componentGlob?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs component tests using Playwright's component testing capabilities
|
|
15
|
+
* This allows testing individual UI components in isolation
|
|
16
|
+
*/
|
|
17
|
+
export declare function runComponentTests(entryPoint: string, options?: ComponentRunnerOptions): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/component/runner.ts"],"names":[],"mappings":"AAMA,OAAO,0BAA0B,CAAC;AAClC,OAAO,6BAA6B,CAAC;AACrC,OAAO,2BAA2B,CAAC;AACnC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAE7B,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB,iBAmC3F"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runComponentTests = runComponentTests;
|
|
37
|
+
// src/component/runner.ts
|
|
38
|
+
const test_1 = require("@playwright/test");
|
|
39
|
+
const glob_1 = require("glob");
|
|
40
|
+
const registry_1 = require("../core/registry");
|
|
41
|
+
// LOAD BACKEND LIBRARIES for component testing
|
|
42
|
+
require("../backend/actions/index");
|
|
43
|
+
require("../backend/assertions/index");
|
|
44
|
+
require("../backend/elements/index");
|
|
45
|
+
require("../backend/api/index");
|
|
46
|
+
require("../backend/auth/index");
|
|
47
|
+
require("../backend/utils/state");
|
|
48
|
+
require("../backend/db/index");
|
|
49
|
+
/**
|
|
50
|
+
* Runs component tests using Playwright's component testing capabilities
|
|
51
|
+
* This allows testing individual UI components in isolation
|
|
52
|
+
*/
|
|
53
|
+
async function runComponentTests(entryPoint, options) {
|
|
54
|
+
const files = (0, glob_1.globSync)(options?.componentGlob || entryPoint);
|
|
55
|
+
if (files.length === 0) {
|
|
56
|
+
console.log(`ā ļø No Component test files found for: ${entryPoint}`);
|
|
57
|
+
}
|
|
58
|
+
for (const file of files) {
|
|
59
|
+
// Import the component test file to register any component-specific steps
|
|
60
|
+
await Promise.resolve(`${file}`).then(s => __importStar(require(s)));
|
|
61
|
+
// Run tests using Playwright's component testing setup
|
|
62
|
+
test_1.test.describe(`Component: ${file}`, () => {
|
|
63
|
+
test_1.test.beforeEach(async ({ page: _page }) => {
|
|
64
|
+
// Component testing setup would happen here
|
|
65
|
+
// In actual component testing, we'd mount components directly
|
|
66
|
+
console.log(`š§ Preparing component test environment for: ${file}`);
|
|
67
|
+
});
|
|
68
|
+
// Iterate through registered steps and create component-specific tests
|
|
69
|
+
for (const step of registry_1.stepRegistry) {
|
|
70
|
+
// Only run steps that are relevant to component testing
|
|
71
|
+
if (isComponentRelevantStep(step)) {
|
|
72
|
+
(0, test_1.test)(`Component step: ${typeof step.pattern === 'string' ? step.pattern : step.pattern.source}`, async ({ page: _page }) => {
|
|
73
|
+
// In component testing context, we might have different parameters
|
|
74
|
+
// For now, we'll just log that this would be a component test
|
|
75
|
+
console.log(`š§Ŗ Running component test for step: ${typeof step.pattern === 'string' ? step.pattern : step.pattern.source}`);
|
|
76
|
+
// Here we would execute the step function with component-specific context
|
|
77
|
+
// await step.fn({ page }, ...args);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Determines if a step is relevant for component testing
|
|
86
|
+
*/
|
|
87
|
+
function isComponentRelevantStep(_step) {
|
|
88
|
+
// For now, consider all steps potentially relevant for component testing
|
|
89
|
+
// In the future, we could have more specific logic
|
|
90
|
+
return true;
|
|
91
|
+
}
|
package/dist/core/runner.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAG7B,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CAC3C;AA8FD,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,QA8LpE"}
|
package/dist/core/runner.js
CHANGED
|
@@ -45,24 +45,82 @@ require("../backend/assertions/index");
|
|
|
45
45
|
require("../backend/elements/index");
|
|
46
46
|
require("../backend/api/index");
|
|
47
47
|
require("../backend/auth/index");
|
|
48
|
+
require("../backend/utils/state");
|
|
48
49
|
require("../backend/db/index");
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Parses a block of Gherkin lines into structured steps.
|
|
52
|
+
*/
|
|
53
|
+
function parseSteps(block) {
|
|
54
|
+
const rawLines = block.split("\n");
|
|
55
|
+
const steps = [];
|
|
56
|
+
let currentStep = null;
|
|
57
|
+
let docStringBuffer = [];
|
|
58
|
+
let isDocStringOpen = false;
|
|
59
|
+
for (const line of rawLines) {
|
|
60
|
+
const trimmedLine = line.trim();
|
|
61
|
+
// A. Handle DocStrings (""")
|
|
62
|
+
if (trimmedLine.startsWith('"""')) {
|
|
63
|
+
isDocStringOpen = !isDocStringOpen;
|
|
64
|
+
if (!isDocStringOpen && currentStep) {
|
|
65
|
+
currentStep.docString = docStringBuffer.join("\n");
|
|
66
|
+
docStringBuffer = [];
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// B. Inside DocString? Capture raw line (preserve indent)
|
|
71
|
+
if (isDocStringOpen) {
|
|
72
|
+
docStringBuffer.push(line);
|
|
73
|
+
continue;
|
|
57
74
|
}
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
// C. Skip Empty Lines, Comments, Tags, and section headers
|
|
76
|
+
if (!trimmedLine ||
|
|
77
|
+
trimmedLine.startsWith("#") ||
|
|
78
|
+
(/^@/.test(trimmedLine) && !/^@[^@]/.test(line)) || // Skip lines that start with @ (but not inline tags like "And I expect #element @tag")
|
|
79
|
+
/^(Background|Scenario|Scenario Outline|Feature):/.test(trimmedLine)) {
|
|
80
|
+
continue;
|
|
60
81
|
}
|
|
61
|
-
|
|
62
|
-
|
|
82
|
+
// D. Handle Data Tables (| col | col |)
|
|
83
|
+
if (trimmedLine.startsWith("|")) {
|
|
84
|
+
if (currentStep) {
|
|
85
|
+
if (!currentStep.dataTable)
|
|
86
|
+
currentStep.dataTable = [];
|
|
87
|
+
const cleanRow = trimmedLine
|
|
88
|
+
.split("|")
|
|
89
|
+
.slice(1, -1)
|
|
90
|
+
.map((c) => c.trim());
|
|
91
|
+
currentStep.dataTable.push(cleanRow);
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
63
94
|
}
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
// E. It is a New Step
|
|
96
|
+
const cleanText = trimmedLine
|
|
97
|
+
.replace(/^(Given|When|Then|And|But)\s+/i, "")
|
|
98
|
+
.replace(/:$/, "")
|
|
99
|
+
.trim();
|
|
100
|
+
currentStep = {
|
|
101
|
+
text: trimmedLine,
|
|
102
|
+
cleanText: cleanText,
|
|
103
|
+
};
|
|
104
|
+
steps.push(currentStep);
|
|
105
|
+
}
|
|
106
|
+
return steps;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Extracts the Background block text from a feature file content.
|
|
110
|
+
* Returns the raw text between "Background:" and the first Scenario.
|
|
111
|
+
*/
|
|
112
|
+
function extractBackgroundBlock(content) {
|
|
113
|
+
const backgroundMatch = content.match(/Background:\s*[^\n]*/);
|
|
114
|
+
if (!backgroundMatch)
|
|
115
|
+
return null;
|
|
116
|
+
const startIndex = backgroundMatch.index + backgroundMatch[0].length;
|
|
117
|
+
const nextSection = content
|
|
118
|
+
.slice(startIndex)
|
|
119
|
+
.search(/(?:(?:@\S+\s*)*(?:Scenario|Scenario Outline):)/);
|
|
120
|
+
const blockEnd = nextSection === -1 ? content.length : startIndex + nextSection;
|
|
121
|
+
return content.slice(startIndex, blockEnd);
|
|
122
|
+
}
|
|
123
|
+
function runTests(featureGlob, options) {
|
|
66
124
|
// Also show ALL steps if there are few
|
|
67
125
|
if (registry_1.stepRegistry.length <= 10) {
|
|
68
126
|
registry_1.stepRegistry.forEach((step, index) => {
|
|
@@ -86,21 +144,50 @@ function runTests(featureGlob, options) {
|
|
|
86
144
|
}
|
|
87
145
|
for (const file of files) {
|
|
88
146
|
const content = fs.readFileSync(file, "utf8");
|
|
89
|
-
// 1. CAPTURE FEATURE TAGS
|
|
90
|
-
|
|
147
|
+
// 1. CAPTURE FEATURE TAGS (excluding comments)
|
|
148
|
+
// First, let's create a version of the content that excludes comment lines
|
|
149
|
+
// A comment line is one that starts with # followed by a space or end of line
|
|
150
|
+
const contentLines = content.split('\n');
|
|
151
|
+
const nonCommentLines = [];
|
|
152
|
+
for (const line of contentLines) {
|
|
153
|
+
const trimmedLine = line.trim();
|
|
154
|
+
// Skip lines that are comments (start with # followed by space or end of line)
|
|
155
|
+
if (trimmedLine.startsWith('#') && (trimmedLine.length === 1 || /\s/.test(trimmedLine[1]))) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
nonCommentLines.push(line);
|
|
159
|
+
}
|
|
160
|
+
const nonCommentContent = nonCommentLines.join('\n');
|
|
161
|
+
const featureTagMatch = nonCommentContent.match(/((?:@\S+\s*)+)Feature:/);
|
|
91
162
|
const rawFeatureTags = featureTagMatch ? featureTagMatch[1] : "";
|
|
92
163
|
const featureTags = rawFeatureTags.replace(/[\r\n]+/g, " ").trim();
|
|
164
|
+
// Check if the feature has @ignore tag and skip if it does
|
|
165
|
+
if (featureTags.includes('@ignore')) {
|
|
166
|
+
console.log(`āļø Skipping feature due to @ignore tag`);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
93
169
|
const featureMatch = content.match(/Feature:\s*(.+)/);
|
|
94
170
|
const featureName = featureMatch
|
|
95
171
|
? featureMatch[1].trim()
|
|
96
172
|
: "Unnamed Feature";
|
|
97
173
|
test_1.test.describe(featureName, () => {
|
|
98
|
-
// 2.
|
|
99
|
-
|
|
100
|
-
const
|
|
174
|
+
// 2. PARSE BACKGROUND (if present)
|
|
175
|
+
const backgroundBlock = extractBackgroundBlock(content);
|
|
176
|
+
const backgroundSteps = backgroundBlock
|
|
177
|
+
? parseSteps(backgroundBlock)
|
|
178
|
+
: [];
|
|
179
|
+
// 3. SCENARIO REGEX
|
|
180
|
+
// For scenario tags, we need to be more careful about comments
|
|
181
|
+
// We'll process each scenario individually to check for comment lines
|
|
182
|
+
const _scenarioPattern = /(?:((?:@\S+\s*)+))?(?:Scenario|Scenario Outline):\s*(.+)/g;
|
|
101
183
|
let match;
|
|
102
184
|
let foundCount = 0;
|
|
103
|
-
|
|
185
|
+
// 3. SCENARIO REGEX
|
|
186
|
+
// Use the non-comment content for tag matching to avoid commented tags
|
|
187
|
+
const scenarioRegex = /(?:((?:@\S+\s*)+))?(?:Scenario|Scenario Outline):\s*(.+)/g;
|
|
188
|
+
// Reset regex index for each file
|
|
189
|
+
scenarioRegex.lastIndex = 0;
|
|
190
|
+
while ((match = scenarioRegex.exec(nonCommentContent)) !== null) {
|
|
104
191
|
foundCount++;
|
|
105
192
|
const rawScenarioTags = match[1] || "";
|
|
106
193
|
const scenarioTags = rawScenarioTags.replace(/[\r\n]+/g, " ").trim();
|
|
@@ -110,7 +197,13 @@ function runTests(featureGlob, options) {
|
|
|
110
197
|
const fullName = combinedTags
|
|
111
198
|
? `${scenarioName} ${combinedTags}`
|
|
112
199
|
: scenarioName;
|
|
113
|
-
//
|
|
200
|
+
// CHECK FOR IGNORE TAG
|
|
201
|
+
// If the combined tags include @ignore, skip this scenario
|
|
202
|
+
if (combinedTags.includes('@ignore')) {
|
|
203
|
+
console.log(`āļø Skipping scenario "${scenarioName}" due to @ignore tag`);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
// ENV FILTERING
|
|
114
207
|
const activeFilter = options?.tags || envTag;
|
|
115
208
|
if (activeFilter) {
|
|
116
209
|
const targetGroups = activeFilter.split(",").map((t) => t.trim());
|
|
@@ -121,110 +214,66 @@ function runTests(featureGlob, options) {
|
|
|
121
214
|
if (!isMatch)
|
|
122
215
|
continue;
|
|
123
216
|
}
|
|
124
|
-
//
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
217
|
+
// EXTRACT SCENARIO BLOCK from original content
|
|
218
|
+
// Find the corresponding scenario in the original content
|
|
219
|
+
const scenarioPattern = new RegExp(`(?:((?:@\\S+\\s*)+))?\\s*(?:Scenario|Scenario Outline):\\s*${escapeRegExp(scenarioName)}`, 'g');
|
|
220
|
+
const originalMatch = content.match(scenarioPattern);
|
|
221
|
+
if (originalMatch) {
|
|
222
|
+
// Find the exact position of this scenario in the original content
|
|
223
|
+
const scenarioStartPattern = `(?:((?:@\\S+\\s*)+))?\\s*(?:Scenario|Scenario Outline):\\s*${escapeRegExp(scenarioName)}`;
|
|
224
|
+
const _scenarioStartRegex = new RegExp(scenarioStartPattern);
|
|
225
|
+
const scenarioStartMatch = content.match(scenarioStartPattern);
|
|
226
|
+
if (scenarioStartMatch && scenarioStartMatch.index !== undefined) {
|
|
227
|
+
const startIndex = scenarioStartMatch.index + scenarioStartMatch[0].length;
|
|
228
|
+
const nextMatchIndex = content
|
|
229
|
+
.slice(startIndex)
|
|
230
|
+
.search(/(?:(?:@\S+\s*)*(?:Scenario|Scenario Outline):)/);
|
|
231
|
+
const blockEnd = nextMatchIndex === -1 ? content.length : startIndex + nextMatchIndex;
|
|
232
|
+
const scenarioBlock = content.slice(startIndex, blockEnd);
|
|
233
|
+
(0, test_1.test)(fullName, async ({ page }, testInfo) => {
|
|
234
|
+
// ==================================================
|
|
235
|
+
// PHASE 1: PARSE GHERKIN (Preserve Formatting)
|
|
236
|
+
// ==================================================
|
|
237
|
+
const scenarioSteps = parseSteps(scenarioBlock);
|
|
238
|
+
const steps = [...backgroundSteps, ...scenarioSteps];
|
|
239
|
+
// ==================================================
|
|
240
|
+
// PHASE 2: EXECUTE STEPS
|
|
241
|
+
// ==================================================
|
|
242
|
+
console.log(`\nš¹ Scenario: ${scenarioName}`);
|
|
243
|
+
for (const step of steps) {
|
|
244
|
+
const matchResult = findMatchingStep(step.cleanText);
|
|
245
|
+
if (!matchResult) {
|
|
246
|
+
throw new Error(`ā Undefined Step: "${step.cleanText}"`);
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
console.log(` executing: ${step.text.trim()}`);
|
|
250
|
+
const args = [...matchResult.args];
|
|
251
|
+
// Append Data Table if present
|
|
252
|
+
if (step.dataTable && step.dataTable.length > 0) {
|
|
253
|
+
args.push(step.dataTable);
|
|
254
|
+
}
|
|
255
|
+
// Append DocString if present
|
|
256
|
+
if (step.docString) {
|
|
257
|
+
args.push(step.docString);
|
|
258
|
+
}
|
|
259
|
+
await matchResult.fn(page, ...args);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error(`ā Failed at step: "${step.text.trim()}"`);
|
|
263
|
+
const screenshot = await page.screenshot({
|
|
264
|
+
fullPage: true,
|
|
265
|
+
type: "png",
|
|
266
|
+
});
|
|
267
|
+
await testInfo.attach("failure-screenshot", {
|
|
268
|
+
body: screenshot,
|
|
269
|
+
contentType: "image/png",
|
|
270
|
+
});
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
178
273
|
}
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
// E. It is a New Step
|
|
182
|
-
const cleanText = trimmedLine
|
|
183
|
-
.replace(/^(Given|When|Then|And|But)\s+/i, "")
|
|
184
|
-
.replace(/:$/, "") // Remove trailing colon
|
|
185
|
-
.trim();
|
|
186
|
-
currentStep = {
|
|
187
|
-
text: trimmedLine,
|
|
188
|
-
cleanText: cleanText,
|
|
189
|
-
};
|
|
190
|
-
steps.push(currentStep);
|
|
274
|
+
});
|
|
191
275
|
}
|
|
192
|
-
|
|
193
|
-
// PHASE 2: EXECUTE STEPS
|
|
194
|
-
// ==================================================
|
|
195
|
-
console.log(`\nš¹ Scenario: ${scenarioName}`);
|
|
196
|
-
for (const step of steps) {
|
|
197
|
-
const matchResult = findMatchingStep(step.cleanText);
|
|
198
|
-
if (!matchResult) {
|
|
199
|
-
throw new Error(`ā Undefined Step: "${step.cleanText}"`);
|
|
200
|
-
}
|
|
201
|
-
try {
|
|
202
|
-
console.log(` executing: ${step.text.trim()}`);
|
|
203
|
-
const args = [...matchResult.args];
|
|
204
|
-
// Append Data Table if present
|
|
205
|
-
if (step.dataTable && step.dataTable.length > 0) {
|
|
206
|
-
args.push(step.dataTable);
|
|
207
|
-
}
|
|
208
|
-
// Append DocString if present
|
|
209
|
-
if (step.docString) {
|
|
210
|
-
args.push(step.docString);
|
|
211
|
-
}
|
|
212
|
-
await matchResult.fn(page, ...args);
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
console.error(`ā Failed at step: "${step.text.trim()}"`);
|
|
216
|
-
const screenshot = await page.screenshot({
|
|
217
|
-
fullPage: true,
|
|
218
|
-
type: "png",
|
|
219
|
-
});
|
|
220
|
-
await testInfo.attach("failure-screenshot", {
|
|
221
|
-
body: screenshot,
|
|
222
|
-
contentType: "image/png",
|
|
223
|
-
});
|
|
224
|
-
throw error;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
});
|
|
276
|
+
}
|
|
228
277
|
}
|
|
229
278
|
if (foundCount === 0) {
|
|
230
279
|
console.warn(`ā ļø File matched but 0 Scenarios found in: ${file}`);
|
|
@@ -232,6 +281,12 @@ function runTests(featureGlob, options) {
|
|
|
232
281
|
});
|
|
233
282
|
}
|
|
234
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Escapes special regex characters in a string
|
|
286
|
+
*/
|
|
287
|
+
function escapeRegExp(string) {
|
|
288
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
289
|
+
}
|
|
235
290
|
/**
|
|
236
291
|
* Finds the matching step definition from the registry.
|
|
237
292
|
* Supports: RegExp (with capture groups) and CucumberExpressions.
|
|
@@ -249,7 +304,7 @@ function findMatchingStep(text) {
|
|
|
249
304
|
};
|
|
250
305
|
}
|
|
251
306
|
}
|
|
252
|
-
catch (
|
|
307
|
+
catch (_e) {
|
|
253
308
|
// Continue to next step if Cucumber Expression fails
|
|
254
309
|
continue;
|
|
255
310
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { runTests } from "./core/runner";
|
|
2
2
|
export { Step } from "./core/registry";
|
|
3
3
|
export { getReporters } from "./reporting/index";
|
|
4
|
+
export { runComponentTests } from "./component/index";
|
|
4
5
|
export type { RunnerOptions } from "./core/runner";
|
|
5
6
|
export type { ReportOptions } from "./reporting/index";
|
|
6
7
|
export type { StepAction } from "./core/registry";
|
|
8
|
+
export type { ComponentRunnerOptions } from "./component/index";
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getReporters = exports.Step = exports.runTests = void 0;
|
|
3
|
+
exports.runComponentTests = exports.getReporters = exports.Step = exports.runTests = void 0;
|
|
4
4
|
var runner_1 = require("./core/runner");
|
|
5
5
|
Object.defineProperty(exports, "runTests", { enumerable: true, get: function () { return runner_1.runTests; } });
|
|
6
6
|
var registry_1 = require("./core/registry");
|
|
7
7
|
Object.defineProperty(exports, "Step", { enumerable: true, get: function () { return registry_1.Step; } });
|
|
8
8
|
var index_1 = require("./reporting/index");
|
|
9
9
|
Object.defineProperty(exports, "getReporters", { enumerable: true, get: function () { return index_1.getReporters; } });
|
|
10
|
+
var index_2 = require("./component/index");
|
|
11
|
+
Object.defineProperty(exports, "runComponentTests", { enumerable: true, get: function () { return index_2.runComponentTests; } });
|