playwright-cucumber-ts-steps 1.0.1 → 1.0.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.
Files changed (137) hide show
  1. package/README.md +270 -244
  2. package/dist/backend/actions/formTable.js +34 -0
  3. package/dist/backend/actions/index.js +5 -0
  4. package/dist/backend/actions/interactions.js +23 -0
  5. package/dist/backend/actions/navigation.js +19 -0
  6. package/dist/backend/api/assertions.js +26 -0
  7. package/dist/backend/api/index.js +5 -0
  8. package/dist/backend/api/mock.js +75 -0
  9. package/dist/backend/api/requests.js +86 -0
  10. package/dist/backend/api/state.js +15 -0
  11. package/dist/backend/assertions/expectVisible.js +8 -0
  12. package/dist/backend/assertions/index.js +5 -0
  13. package/dist/backend/assertions/pageState.js +25 -0
  14. package/dist/backend/assertions/text.js +20 -0
  15. package/dist/backend/assertions/visibility.js +20 -0
  16. package/dist/backend/auth/index.js +71 -0
  17. package/dist/backend/db/index.js +6 -0
  18. package/dist/backend/db/state.js +24 -0
  19. package/dist/backend/db/steps.js +43 -0
  20. package/dist/backend/elements/alerts.js +21 -0
  21. package/dist/backend/elements/forms.js +59 -0
  22. package/dist/backend/elements/frames.js +25 -0
  23. package/dist/backend/elements/index.js +5 -0
  24. package/dist/core/registry.js +20 -0
  25. package/dist/core/runner.js +151 -0
  26. package/dist/index.js +10 -0
  27. package/dist/reporting/index.js +43 -0
  28. package/package.json +19 -101
  29. package/LICENSE +0 -21
  30. package/lib/actions/clickSteps.d.ts +0 -251
  31. package/lib/actions/clickSteps.js +0 -415
  32. package/lib/actions/cookieSteps.d.ts +0 -18
  33. package/lib/actions/cookieSteps.js +0 -93
  34. package/lib/actions/debugSteps.d.ts +0 -14
  35. package/lib/actions/debugSteps.js +0 -23
  36. package/lib/actions/elementFindSteps.d.ts +0 -668
  37. package/lib/actions/elementFindSteps.js +0 -931
  38. package/lib/actions/fillFormSteps.d.ts +0 -69
  39. package/lib/actions/fillFormSteps.js +0 -237
  40. package/lib/actions/index.d.ts +0 -11
  41. package/lib/actions/index.js +0 -28
  42. package/lib/actions/inputSteps.d.ts +0 -218
  43. package/lib/actions/inputSteps.js +0 -343
  44. package/lib/actions/interceptionSteps.d.ts +0 -169
  45. package/lib/actions/interceptionSteps.js +0 -291
  46. package/lib/actions/miscSteps.d.ts +0 -645
  47. package/lib/actions/miscSteps.js +0 -1061
  48. package/lib/actions/mouseSteps.d.ts +0 -143
  49. package/lib/actions/mouseSteps.js +0 -234
  50. package/lib/actions/scrollSteps.d.ts +0 -82
  51. package/lib/actions/scrollSteps.js +0 -123
  52. package/lib/actions/storageSteps.d.ts +0 -174
  53. package/lib/actions/storageSteps.js +0 -292
  54. package/lib/assertions/buttonAndTextVisibilitySteps.d.ts +0 -245
  55. package/lib/assertions/buttonAndTextVisibilitySteps.js +0 -401
  56. package/lib/assertions/cookieSteps.d.ts +0 -75
  57. package/lib/assertions/cookieSteps.js +0 -113
  58. package/lib/assertions/elementSteps.d.ts +0 -264
  59. package/lib/assertions/elementSteps.js +0 -388
  60. package/lib/assertions/formInputSteps.d.ts +0 -248
  61. package/lib/assertions/formInputSteps.js +0 -350
  62. package/lib/assertions/index.d.ts +0 -10
  63. package/lib/assertions/index.js +0 -27
  64. package/lib/assertions/interceptionRequestsSteps.d.ts +0 -353
  65. package/lib/assertions/interceptionRequestsSteps.js +0 -593
  66. package/lib/assertions/locationSteps.d.ts +0 -217
  67. package/lib/assertions/locationSteps.js +0 -310
  68. package/lib/assertions/roleTestIdSteps.d.ts +0 -159
  69. package/lib/assertions/roleTestIdSteps.js +0 -221
  70. package/lib/assertions/semanticSteps.d.ts +0 -176
  71. package/lib/assertions/semanticSteps.js +0 -252
  72. package/lib/assertions/storageSteps.d.ts +0 -149
  73. package/lib/assertions/storageSteps.js +0 -210
  74. package/lib/assertions/visualSteps.d.ts +0 -74
  75. package/lib/assertions/visualSteps.js +0 -209
  76. package/lib/custom_setups/loginHooks.d.ts +0 -1
  77. package/lib/custom_setups/loginHooks.js +0 -130
  78. package/lib/helpers/checkPeerDeps.d.ts +0 -1
  79. package/lib/helpers/checkPeerDeps.js +0 -19
  80. package/lib/helpers/compareSnapshots.d.ts +0 -6
  81. package/lib/helpers/compareSnapshots.js +0 -20
  82. package/lib/helpers/hooks.d.ts +0 -1
  83. package/lib/helpers/hooks.js +0 -210
  84. package/lib/helpers/utils/fakerUtils.d.ts +0 -1
  85. package/lib/helpers/utils/fakerUtils.js +0 -60
  86. package/lib/helpers/utils/index.d.ts +0 -4
  87. package/lib/helpers/utils/index.js +0 -20
  88. package/lib/helpers/utils/optionsUtils.d.ts +0 -24
  89. package/lib/helpers/utils/optionsUtils.js +0 -88
  90. package/lib/helpers/utils/resolveUtils.d.ts +0 -6
  91. package/lib/helpers/utils/resolveUtils.js +0 -72
  92. package/lib/helpers/utils/sessionUtils.d.ts +0 -3
  93. package/lib/helpers/utils/sessionUtils.js +0 -40
  94. package/lib/helpers/world.d.ts +0 -34
  95. package/lib/helpers/world.js +0 -110
  96. package/lib/iframes/frames.d.ts +0 -1
  97. package/lib/iframes/frames.js +0 -11
  98. package/lib/index.d.ts +0 -10
  99. package/lib/index.js +0 -28
  100. package/lib/register.d.ts +0 -1
  101. package/lib/register.js +0 -6
  102. package/src/actions/clickSteps.ts +0 -429
  103. package/src/actions/cookieSteps.ts +0 -95
  104. package/src/actions/debugSteps.ts +0 -21
  105. package/src/actions/elementFindSteps.ts +0 -961
  106. package/src/actions/fillFormSteps.ts +0 -270
  107. package/src/actions/index.ts +0 -12
  108. package/src/actions/inputSteps.ts +0 -354
  109. package/src/actions/interceptionSteps.ts +0 -325
  110. package/src/actions/miscSteps.ts +0 -1144
  111. package/src/actions/mouseSteps.ts +0 -256
  112. package/src/actions/scrollSteps.ts +0 -122
  113. package/src/actions/storageSteps.ts +0 -308
  114. package/src/assertions/buttonAndTextVisibilitySteps.ts +0 -436
  115. package/src/assertions/cookieSteps.ts +0 -131
  116. package/src/assertions/elementSteps.ts +0 -432
  117. package/src/assertions/formInputSteps.ts +0 -377
  118. package/src/assertions/index.ts +0 -11
  119. package/src/assertions/interceptionRequestsSteps.ts +0 -640
  120. package/src/assertions/locationSteps.ts +0 -315
  121. package/src/assertions/roleTestIdSteps.ts +0 -254
  122. package/src/assertions/semanticSteps.ts +0 -267
  123. package/src/assertions/storageSteps.ts +0 -250
  124. package/src/assertions/visualSteps.ts +0 -275
  125. package/src/custom_setups/loginHooks.ts +0 -154
  126. package/src/helpers/checkPeerDeps.ts +0 -19
  127. package/src/helpers/compareSnapshots.ts +0 -35
  128. package/src/helpers/hooks.ts +0 -212
  129. package/src/helpers/utils/fakerUtils.ts +0 -64
  130. package/src/helpers/utils/index.ts +0 -4
  131. package/src/helpers/utils/optionsUtils.ts +0 -104
  132. package/src/helpers/utils/resolveUtils.ts +0 -74
  133. package/src/helpers/utils/sessionUtils.ts +0 -36
  134. package/src/helpers/world.ts +0 -119
  135. package/src/iframes/frames.ts +0 -15
  136. package/src/index.ts +0 -18
  137. package/src/register.ts +0 -4
@@ -1,130 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const cucumber_1 = require("@cucumber/cucumber");
8
- const resolveUtils_1 = require("../helpers/utils/resolveUtils");
9
- // Step 1: Check and load existing session if valid
10
- (0, cucumber_1.When)("I login with a session data {string}", async function (sessionName) {
11
- const sessionPath = (0, resolveUtils_1.resolveSessionPath)(this, sessionName);
12
- this.data.sessionFile = sessionPath;
13
- if (fs_1.default.existsSync(sessionPath)) {
14
- try {
15
- await this.context?.addCookies(JSON.parse(fs_1.default.readFileSync(sessionPath, "utf-8")).cookies || []);
16
- this.log?.(`✅ Loaded session from ${sessionPath}`);
17
- }
18
- catch (err) {
19
- this.log?.(`⚠️ Failed to apply session: ${err.message}`);
20
- }
21
- }
22
- else {
23
- this.log?.(`⚠️ Session file not found: ${sessionPath}`);
24
- }
25
- });
26
- /**
27
- * @step
28
- * @description Saves the current browser context (cookies, localStorage, sessionStorage) as a session file.
29
- * @example
30
- * When I save session as "my-session"
31
- */
32
- (0, cucumber_1.When)(/^I save session as "([^"]+)"$/, async function (sessionName) {
33
- const sessionPath = (0, resolveUtils_1.resolveSessionPath)(this, sessionName);
34
- const cookies = await this.context.cookies();
35
- const [localStorageData, sessionStorageData] = await this.page.evaluate(() => {
36
- const toPairs = (store) => Object.entries(store);
37
- return [
38
- [{ origin: location.origin, values: toPairs(localStorage) }],
39
- [{ origin: location.origin, values: toPairs(sessionStorage) }],
40
- ];
41
- });
42
- const sessionData = {
43
- cookies,
44
- localStorage: localStorageData,
45
- sessionStorage: sessionStorageData,
46
- };
47
- try {
48
- fs_1.default.writeFileSync(sessionPath, JSON.stringify(sessionData, null, 2));
49
- this.log?.(`💾 Saved session as "${sessionName}"`);
50
- }
51
- catch (err) {
52
- this.log?.(`❌ Failed to save session "${sessionName}": ${err.message}`);
53
- }
54
- });
55
- /**
56
- * @step
57
- * @description Removes a session file with the given name.
58
- * @example
59
- * When I clear session "my-session"
60
- */
61
- (0, cucumber_1.When)("I clear session {string}", function (sessionName) {
62
- const sessionPath = (0, resolveUtils_1.resolveSessionPath)(this, sessionName);
63
- if (fs_1.default.existsSync(sessionPath)) {
64
- fs_1.default.unlinkSync(sessionPath);
65
- this.log?.(`🧹 Cleared session: ${sessionPath}`);
66
- }
67
- else {
68
- this.log?.(`⚠️ Session not found: ${sessionPath}`);
69
- }
70
- });
71
- /**
72
- * @step
73
- * @description Restores cookies, localStorage, and sessionStorage from a session file. Optionally reloads the page.
74
- * @example
75
- * When I restore session cookies "my-session"
76
- * When I restore session cookies "my-session" with reload "false"
77
- */
78
- (0, cucumber_1.When)(/^I restore session cookies "([^"]+)"(?: with reload "(true|false)")?$/, async function (sessionName, reload = "true") {
79
- const sessionPath = (0, resolveUtils_1.resolveSessionPath)(this, sessionName);
80
- if (!fs_1.default.existsSync(sessionPath)) {
81
- this.log?.(`❌ Session file not found: ${sessionPath}`);
82
- return;
83
- }
84
- const sessionData = JSON.parse(fs_1.default.readFileSync(sessionPath, "utf-8"));
85
- const { cookies = [], localStorage = [], sessionStorage = [] } = sessionData;
86
- try {
87
- // Clear & set cookies
88
- if (cookies.length) {
89
- const existing = await this.context.cookies();
90
- if (existing.length)
91
- await this.context.clearCookies();
92
- await this.context.addCookies(cookies);
93
- this.log?.(`🍪 Cookies restored from "${sessionName}"`);
94
- }
95
- // Apply storage into page context
96
- await this.page.goto("about:blank");
97
- if (localStorage.length > 0) {
98
- for (const entry of localStorage) {
99
- await this.page.addInitScript(([origin, values]) => {
100
- if (window.origin === origin) {
101
- for (const [key, val] of values) {
102
- localStorage.setItem(key, val);
103
- }
104
- }
105
- }, [entry.origin, entry.values]);
106
- }
107
- this.log?.("📦 localStorage restored");
108
- }
109
- if (sessionStorage.length > 0) {
110
- for (const entry of sessionStorage) {
111
- await this.page.addInitScript(([origin, values]) => {
112
- if (window.origin === origin) {
113
- for (const [key, val] of values) {
114
- sessionStorage.setItem(key, val);
115
- }
116
- }
117
- }, [entry.origin, entry.values]);
118
- }
119
- this.log?.("🗄️ sessionStorage restored");
120
- }
121
- // Final reload to apply context if requested
122
- if (reload !== "false") {
123
- await this.page.reload();
124
- this.log?.("🔄 Page reloaded to apply restored session");
125
- }
126
- }
127
- catch (err) {
128
- this.log?.(`❌ Error restoring session: ${err.message}`);
129
- }
130
- });
@@ -1 +0,0 @@
1
- export declare function checkPeerDependencies(dependencies: string[]): void;
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkPeerDependencies = checkPeerDependencies;
4
- function checkPeerDependencies(dependencies) {
5
- const missing = [];
6
- for (const dep of dependencies) {
7
- try {
8
- require.resolve(dep);
9
- }
10
- catch {
11
- missing.push(dep);
12
- }
13
- }
14
- if (missing.length) {
15
- console.warn(`\n❌ Missing peer dependencies: ${missing.join(", ")}` +
16
- `\nPlease install them in your project:\n\n` +
17
- `npm install --save-dev ${missing.join(" ")}\n`);
18
- }
19
- }
@@ -1,6 +0,0 @@
1
- export declare function compareSnapshots({ actualPath, baselinePath, diffPath, threshold, }: {
2
- actualPath: string;
3
- baselinePath: string;
4
- diffPath: string;
5
- threshold?: number;
6
- }): number;
@@ -1,20 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.compareSnapshots = compareSnapshots;
7
- const fs_1 = __importDefault(require("fs"));
8
- const pixelmatch_1 = __importDefault(require("pixelmatch"));
9
- const pngjs_1 = require("pngjs");
10
- function compareSnapshots({ actualPath, baselinePath, diffPath, threshold = 0.1, }) {
11
- const actual = pngjs_1.PNG.sync.read(fs_1.default.readFileSync(actualPath));
12
- const baseline = pngjs_1.PNG.sync.read(fs_1.default.readFileSync(baselinePath));
13
- if (actual.width !== baseline.width || actual.height !== baseline.height) {
14
- throw new Error("Snapshot size mismatch");
15
- }
16
- const diff = new pngjs_1.PNG({ width: actual.width, height: actual.height });
17
- const numDiffPixels = (0, pixelmatch_1.default)(actual.data, baseline.data, diff.data, actual.width, actual.height, { threshold });
18
- fs_1.default.writeFileSync(diffPath, pngjs_1.PNG.sync.write(diff));
19
- return numDiffPixels;
20
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,210 +0,0 @@
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
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- const fs_1 = __importDefault(require("fs"));
40
- const path_1 = __importDefault(require("path"));
41
- const cucumber_1 = require("@cucumber/cucumber");
42
- const dotenv = __importStar(require("dotenv"));
43
- const playwright_1 = require("playwright");
44
- const compareSnapshots_1 = require("./compareSnapshots");
45
- // Set to 30 seconds
46
- (0, cucumber_1.setDefaultTimeout)(30 * 1000);
47
- dotenv.config();
48
- let sharedBrowser;
49
- (0, cucumber_1.BeforeAll)(async () => {
50
- sharedBrowser = await playwright_1.chromium.launch({
51
- headless: process.env.HEADLESS !== "false",
52
- });
53
- console.log("🚀 Launched shared browser for all scenarios");
54
- });
55
- (0, cucumber_1.AfterAll)(async () => {
56
- await sharedBrowser?.close();
57
- console.log("🧹 Closed shared browser after all scenarios");
58
- });
59
- (0, cucumber_1.Before)(async function (scenario) {
60
- const params = this.parameters || {};
61
- const ARTIFACT_DIR = params.artifactDir || process.env.TEST_ARTIFACT_DIR || "test-artifacts";
62
- const SCREENSHOT_DIR = path_1.default.resolve(ARTIFACT_DIR, "screenshots");
63
- const VIDEO_DIR = path_1.default.resolve(ARTIFACT_DIR, "videos");
64
- const TRACE_DIR = path_1.default.resolve(ARTIFACT_DIR, "traces");
65
- const SESSION_FILE = path_1.default.resolve(ARTIFACT_DIR, "auth-cookies", "session.json");
66
- this.data.artifactDir = ARTIFACT_DIR;
67
- this.data.screenshotDir = SCREENSHOT_DIR;
68
- this.data.videoDir = VIDEO_DIR;
69
- this.data.traceDir = TRACE_DIR;
70
- this.data.sessionFile = SESSION_FILE;
71
- // Modes: "false" | "fail" | "all"
72
- const traceMode = (params.enableTrace || process.env.ENABLE_TRACE || "false").toLowerCase();
73
- const screenshotMode = (params.enableScreenshots ||
74
- process.env.ENABLE_SCREENSHOTS ||
75
- "false").toLowerCase();
76
- const videoMode = (params.enableVideos || process.env.ENABLE_VIDEOS || "false").toLowerCase();
77
- this.data.traceMode = traceMode;
78
- this.data.screenshotMode = screenshotMode;
79
- this.data.videoMode = videoMode;
80
- const isMobileTag = scenario.pickle.tags.some((t) => t.name === "@mobile");
81
- const deviceName = params.device || process.env.MOBILE_DEVICE || (isMobileTag ? "iPhone 13 Pro" : null);
82
- const deviceSettings = deviceName ? playwright_1.devices[deviceName] : undefined;
83
- if (deviceName && !deviceSettings) {
84
- throw new Error(`🚫 Invalid MOBILE_DEVICE: "${deviceName}" is not recognized by Playwright.`);
85
- }
86
- const isVisualTest = params.enableVisualTest ??
87
- (process.env.ENABLE_VISUAL_TEST === "true" ||
88
- scenario.pickle.tags.some((t) => t.name === "@visual"));
89
- this.data.enableVisualTest = isVisualTest;
90
- if (isVisualTest)
91
- process.env.VISUAL_TEST = "true";
92
- const contextOptions = {
93
- ...(videoMode !== "false" ? { recordVideo: { dir: VIDEO_DIR } } : {}),
94
- ...(deviceSettings || {}),
95
- };
96
- if (fs_1.default.existsSync(SESSION_FILE)) {
97
- contextOptions.storageState = SESSION_FILE;
98
- this.log?.("✅ Reusing session from saved file.");
99
- }
100
- const context = await sharedBrowser.newContext(contextOptions);
101
- const page = await context.newPage();
102
- this.browser = sharedBrowser;
103
- this.context = context;
104
- this.page = page;
105
- if (traceMode !== "false") {
106
- await context.tracing.start({
107
- screenshots: true,
108
- snapshots: true,
109
- sources: true,
110
- });
111
- this.data.tracingStarted = true;
112
- this.log?.(`🧪 Tracing started (${traceMode})`);
113
- }
114
- if (deviceName)
115
- this.log?.(`📱 Mobile emulation enabled (${deviceName})`);
116
- });
117
- (0, cucumber_1.After)(async function (scenario) {
118
- const name = scenario.pickle.name.replace(/[^a-z0-9]+/gi, "_").toLowerCase();
119
- const failed = scenario.result?.status === "FAILED";
120
- const mode = (value) => value?.toLowerCase();
121
- const screenshotMode = mode(this.parameters?.enableScreenshots || process.env.ENABLE_SCREENSHOTS);
122
- const videoMode = mode(this.parameters?.enableVideos || process.env.ENABLE_VIDEOS);
123
- const traceMode = mode(this.parameters?.enableTrace || process.env.ENABLE_TRACE);
124
- const shouldSaveScreenshot = screenshotMode === "all" || (screenshotMode === "fail" && failed);
125
- const shouldSaveVideo = videoMode === "all" || (videoMode === "fail" && failed);
126
- const shouldSaveTrace = traceMode === "all" || (traceMode === "fail" && failed);
127
- // 📸 Screenshot
128
- if (shouldSaveScreenshot && this.page) {
129
- const screenshotPath = path_1.default.join(this.data.screenshotDir, `${failed ? "failed-" : ""}${name}.png`);
130
- try {
131
- fs_1.default.mkdirSync(this.data.screenshotDir, { recursive: true });
132
- await this.page.screenshot({ path: screenshotPath, fullPage: true });
133
- console.log(`🖼️ Screenshot saved: ${screenshotPath}`);
134
- }
135
- catch (err) {
136
- console.warn("❌ Failed to save screenshot:", err);
137
- }
138
- }
139
- // 🎥 Video
140
- if (this.page && videoMode !== "false") {
141
- try {
142
- const video = this.page.video();
143
- if (video) {
144
- const rawPath = await video.path();
145
- if (fs_1.default.existsSync(rawPath)) {
146
- const finalPath = path_1.default.join(this.data.videoDir, `${failed ? "failed-" : ""}${name}.webm`);
147
- fs_1.default.mkdirSync(this.data.videoDir, { recursive: true });
148
- shouldSaveVideo ? fs_1.default.renameSync(rawPath, finalPath) : fs_1.default.unlinkSync(rawPath);
149
- console.log(`${shouldSaveVideo ? "🎥 Video saved" : "🧹 Deleted video"}: ${finalPath}`);
150
- }
151
- }
152
- }
153
- catch (err) {
154
- console.warn(`⚠️ Video error: ${err.message}`);
155
- }
156
- }
157
- // 🧪 Tracing
158
- if (this.context && this.data.tracingStarted) {
159
- const tracePath = path_1.default.join(this.data.artifactDir, "traces", `${name}.zip`);
160
- try {
161
- fs_1.default.mkdirSync(path_1.default.dirname(tracePath), { recursive: true });
162
- await this.context.tracing.stop({ path: tracePath });
163
- shouldSaveTrace
164
- ? console.log(`📦 Trace saved: ${tracePath}`)
165
- : (fs_1.default.existsSync(tracePath) && fs_1.default.unlinkSync(tracePath),
166
- console.log(`🧹 Trace discarded: ${tracePath}`));
167
- }
168
- catch (err) {
169
- console.warn("❌ Trace handling error:", err);
170
- }
171
- }
172
- // 🧪 Visual regression
173
- if (this.page && this.data.enableVisualTest) {
174
- const BASELINE_DIR = path_1.default.resolve(this.data.artifactDir, "snapshots/baseline");
175
- const DIFF_DIR = path_1.default.resolve(this.data.artifactDir, "snapshots/diff");
176
- fs_1.default.mkdirSync(BASELINE_DIR, { recursive: true });
177
- fs_1.default.mkdirSync(DIFF_DIR, { recursive: true });
178
- const baselinePath = path_1.default.join(BASELINE_DIR, `${name}.png`);
179
- const actualPath = path_1.default.join(DIFF_DIR, `${name}.actual.png`);
180
- const diffPath = path_1.default.join(DIFF_DIR, `${name}.diff.png`);
181
- await this.page.screenshot({ path: actualPath, fullPage: true });
182
- if (!fs_1.default.existsSync(baselinePath)) {
183
- fs_1.default.copyFileSync(actualPath, baselinePath);
184
- console.log(`📸 Created baseline image: ${baselinePath}`);
185
- }
186
- else {
187
- try {
188
- const diffPixels = (0, compareSnapshots_1.compareSnapshots)({
189
- actualPath,
190
- baselinePath,
191
- diffPath,
192
- threshold: 0.1,
193
- });
194
- console.log(diffPixels > 0
195
- ? `⚠️ Visual diff found (${diffPixels} pixels): ${diffPath}`
196
- : "✅ No visual changes detected");
197
- }
198
- catch (err) {
199
- console.warn("❌ Snapshot comparison failed:", err);
200
- }
201
- }
202
- }
203
- // Cleanup
204
- try {
205
- await this.cleanup(scenario);
206
- }
207
- catch (err) {
208
- this.log?.("❌ Error during cleanup: " + err.message);
209
- }
210
- });
@@ -1 +0,0 @@
1
- export declare function evaluateFaker(value: string): string;
@@ -1,60 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.evaluateFaker = evaluateFaker;
7
- const faker_1 = require("@faker-js/faker");
8
- const dayjs_1 = __importDefault(require("dayjs"));
9
- const fakerMapping = {
10
- "First Name": () => faker_1.faker.person.middleName(),
11
- Name: () => faker_1.faker.person.middleName(),
12
- "Last Name": () => faker_1.faker.person.middleName(),
13
- Email: () => faker_1.faker.internet.email(),
14
- "Phone Number": () => faker_1.faker.string.numeric(10),
15
- Number: () => faker_1.faker.string.numeric(11),
16
- "Complete Number": () => faker_1.faker.string.numeric(11),
17
- "App Colour": () => faker_1.faker.color.rgb(),
18
- "App Name": () => faker_1.faker.commerce.productName(),
19
- "Role Name": () => faker_1.faker.person.jobTitle(),
20
- "Company Name": () => faker_1.faker.company.name(),
21
- "Full Name": () => faker_1.faker.person.fullName(),
22
- "Disposable Email": () => faker_1.faker.internet.email({ provider: "inboxkitten.com" }),
23
- "ALpha Numeric": () => faker_1.faker.string.numeric(11) + "e",
24
- "Lorem Word": () => faker_1.faker.lorem.sentences({ min: 1, max: 3 }),
25
- Word: () => faker_1.faker.lorem.word({ length: { min: 5, max: 11 } }),
26
- "Current Date": () => (0, dayjs_1.default)().format("YYYY-MM-DD"),
27
- "Current Date2": () => new Date().toISOString().split("T")[0],
28
- MonthsFromNow: (months) => {
29
- const monthsToAdd = parseInt(months || "0", 10);
30
- return (0, dayjs_1.default)().add(monthsToAdd, "month").format("YYYY-MM-DD");
31
- },
32
- MonthsAgo: (months) => {
33
- const monthsToSubtract = parseInt(months || "0", 10);
34
- return (0, dayjs_1.default)().subtract(monthsToSubtract, "month").format("YYYY-MM-DD");
35
- },
36
- WeeksFromNow: (weeks) => {
37
- const weeksToAdd = parseInt(weeks || "0", 10);
38
- return (0, dayjs_1.default)().add(weeksToAdd, "week").format("YYYY-MM-DD");
39
- },
40
- WeeksAgo: (weeks) => {
41
- const weeksToSubtract = parseInt(weeks || "0", 10);
42
- return (0, dayjs_1.default)().subtract(weeksToSubtract, "week").format("YYYY-MM-DD");
43
- },
44
- DaysFromNow: (days) => {
45
- const daysToAdd = parseInt(days || "0", 10);
46
- return (0, dayjs_1.default)().add(daysToAdd, "day").format("YYYY-MM-DD");
47
- },
48
- DaysAgo: (days) => {
49
- const daysToSubtract = parseInt(days || "0", 10);
50
- return (0, dayjs_1.default)().subtract(daysToSubtract, "day").format("YYYY-MM-DD");
51
- },
52
- };
53
- function evaluateFaker(value) {
54
- const [key, param] = value.split(":");
55
- const fn = fakerMapping[key];
56
- if (typeof fn === "function") {
57
- return fn(param);
58
- }
59
- return value; // fallback to raw value if not mapped
60
- }
@@ -1,4 +0,0 @@
1
- export * from "./fakerUtils";
2
- export * from "./optionsUtils";
3
- export * from "./resolveUtils";
4
- export * from "./sessionUtils";
@@ -1,20 +0,0 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./fakerUtils"), exports);
18
- __exportStar(require("./optionsUtils"), exports);
19
- __exportStar(require("./resolveUtils"), exports);
20
- __exportStar(require("./sessionUtils"), exports);
@@ -1,24 +0,0 @@
1
- import type { DataTable } from "@cucumber/cucumber";
2
- import type { Locator } from "@playwright/test";
3
- type ClickOptions = Parameters<Locator["click"]>[0];
4
- type DblClickOptions = Parameters<Locator["dblclick"]>[0];
5
- type HoverOptions = Parameters<Locator["hover"]>[0];
6
- type FillOptions = Parameters<Locator["fill"]>[1];
7
- type TypeOptions = Parameters<Locator["type"]>[1];
8
- type CheckOptions = Parameters<Locator["check"]>[0];
9
- type UncheckOptions = Parameters<Locator["uncheck"]>[0];
10
- type SelectOptionOptions = Parameters<Locator["selectOption"]>[1];
11
- export declare function parseClickOptions(table?: DataTable): Partial<ClickOptions>;
12
- export declare function parseDblClickOptions(table?: DataTable): Partial<DblClickOptions>;
13
- export declare function parseHoverOptions(table?: DataTable): Partial<HoverOptions>;
14
- export declare function parseTypeOptions(table?: DataTable): Partial<TypeOptions>;
15
- export declare function parseFillOptions(table?: DataTable): Partial<FillOptions>;
16
- export declare function parseCheckOptions(table?: DataTable): Partial<CheckOptions>;
17
- export declare function parseUncheckOptions(table?: DataTable): Partial<UncheckOptions>;
18
- export declare function parseSelectOptions(table?: DataTable): Partial<SelectOptionOptions>;
19
- export declare function parseGenericOptions(table?: DataTable): Record<string, any>;
20
- export declare function parseExpectOptions(table?: DataTable): {
21
- timeout?: number;
22
- log?: boolean;
23
- };
24
- export {};
@@ -1,88 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseClickOptions = parseClickOptions;
4
- exports.parseDblClickOptions = parseDblClickOptions;
5
- exports.parseHoverOptions = parseHoverOptions;
6
- exports.parseTypeOptions = parseTypeOptions;
7
- exports.parseFillOptions = parseFillOptions;
8
- exports.parseCheckOptions = parseCheckOptions;
9
- exports.parseUncheckOptions = parseUncheckOptions;
10
- exports.parseSelectOptions = parseSelectOptions;
11
- exports.parseGenericOptions = parseGenericOptions;
12
- exports.parseExpectOptions = parseExpectOptions;
13
- function parseClickOptions(table) {
14
- return parseGenericOptions(table);
15
- }
16
- function parseDblClickOptions(table) {
17
- return parseGenericOptions(table);
18
- }
19
- function parseHoverOptions(table) {
20
- return parseGenericOptions(table);
21
- }
22
- function parseTypeOptions(table) {
23
- return parseGenericOptions(table);
24
- }
25
- function parseFillOptions(table) {
26
- return parseGenericOptions(table);
27
- }
28
- function parseCheckOptions(table) {
29
- return parseGenericOptions(table);
30
- }
31
- function parseUncheckOptions(table) {
32
- return parseGenericOptions(table);
33
- }
34
- function parseSelectOptions(table) {
35
- return parseGenericOptions(table);
36
- }
37
- function parseGenericOptions(table) {
38
- if (!table)
39
- return {};
40
- const options = {};
41
- const rows = table.raw();
42
- for (const [key, value] of rows) {
43
- switch (key) {
44
- case "timeout":
45
- case "delay":
46
- case "clickCount":
47
- options[key] = Number(value);
48
- break;
49
- case "force":
50
- case "noWaitAfter":
51
- case "strict":
52
- case "trial":
53
- options[key] = value === "true";
54
- break;
55
- case "modifiers":
56
- options.modifiers = value.split(",").map((v) => v.trim());
57
- break;
58
- case "button":
59
- if (["left", "middle", "right"].includes(value)) {
60
- options.button = value;
61
- }
62
- else {
63
- throw new Error(`Invalid button option: "${value}"`);
64
- }
65
- break;
66
- case "position":
67
- const [x, y] = value.split(",").map((n) => Number(n.trim()));
68
- if (isNaN(x) || isNaN(y)) {
69
- throw new Error(`Invalid position format: "${value}"`);
70
- }
71
- options.position = { x, y };
72
- break;
73
- default:
74
- console.warn(`[⚠️ parseGenericOptions] Unknown option "${key}"`);
75
- break;
76
- }
77
- }
78
- return options;
79
- }
80
- function parseExpectOptions(table) {
81
- if (!table)
82
- return {};
83
- const obj = Object.fromEntries(table.rows());
84
- return {
85
- timeout: obj.timeout ? Number(obj.timeout) : undefined,
86
- log: obj.log === "true",
87
- };
88
- }
@@ -1,6 +0,0 @@
1
- import type { CustomWorld } from "../world";
2
- export declare function resolveValue(input: string): string;
3
- export declare function resolveLoginValue(raw: string, world: CustomWorld): string | undefined;
4
- export declare function deriveSessionName(emailOrUser: string, fallback?: string): string;
5
- export declare function resolveSessionPath(world: CustomWorld, name: string): string;
6
- export declare function normalizeDeviceName(name: string): string;