lexxit-automation-framework 2.0.1 → 2.0.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-obf/app.js +1 -0
- package/dist-obf/controllers/controller.js +1 -0
- package/dist-obf/core/BrowserManager.js +1 -0
- package/dist-obf/core/PlaywrightEngine.js +1 -0
- package/dist-obf/core/ScreenshotManager.js +1 -0
- package/dist-obf/core/TestData.js +1 -0
- package/dist-obf/core/TestExecutor.js +1 -0
- package/dist-obf/core/handlers/AllHandlers.js +1 -0
- package/dist-obf/core/handlers/BaseHandler.js +1 -0
- package/dist-obf/core/handlers/ClickHandler.js +1 -0
- package/dist-obf/core/handlers/CustomCodeHandler.js +1 -0
- package/dist-obf/core/handlers/DropdownHandler.js +1 -0
- package/dist-obf/core/handlers/InputHandler.js +1 -0
- package/dist-obf/core/registry/ActionRegistry.js +1 -0
- package/dist-obf/installer/frameworkLauncher.js +1 -0
- package/dist-obf/queue/ExecutionQueue.js +1 -0
- package/dist-obf/routes/api.routes.js +1 -0
- package/dist-obf/server.js +1 -0
- package/dist-obf/types/types.js +1 -0
- package/dist-obf/utils/elementHighlight.js +1 -0
- package/dist-obf/utils/locatorHelper.js +1 -0
- package/dist-obf/utils/logger.js +1 -0
- package/dist-obf/utils/response.js +1 -0
- package/dist-obf/utils/responseFormatter.js +1 -0
- package/dist-obf/utils/sseManager.js +1 -0
- package/package.json +8 -4
- package/dist/app.d.ts +0 -2
- package/dist/app.js +0 -26
- package/dist/app.js.map +0 -1
- package/dist/controllers/controller.d.ts +0 -57
- package/dist/controllers/controller.js +0 -263
- package/dist/controllers/controller.js.map +0 -1
- package/dist/core/BrowserManager.d.ts +0 -46
- package/dist/core/BrowserManager.js +0 -377
- package/dist/core/BrowserManager.js.map +0 -1
- package/dist/core/PlaywrightEngine.d.ts +0 -16
- package/dist/core/PlaywrightEngine.js +0 -246
- package/dist/core/PlaywrightEngine.js.map +0 -1
- package/dist/core/ScreenshotManager.d.ts +0 -10
- package/dist/core/ScreenshotManager.js +0 -28
- package/dist/core/ScreenshotManager.js.map +0 -1
- package/dist/core/TestData.d.ts +0 -12
- package/dist/core/TestData.js +0 -29
- package/dist/core/TestData.js.map +0 -1
- package/dist/core/TestExecutor.d.ts +0 -16
- package/dist/core/TestExecutor.js +0 -355
- package/dist/core/TestExecutor.js.map +0 -1
- package/dist/core/handlers/AllHandlers.d.ts +0 -116
- package/dist/core/handlers/AllHandlers.js +0 -648
- package/dist/core/handlers/AllHandlers.js.map +0 -1
- package/dist/core/handlers/BaseHandler.d.ts +0 -16
- package/dist/core/handlers/BaseHandler.js +0 -27
- package/dist/core/handlers/BaseHandler.js.map +0 -1
- package/dist/core/handlers/ClickHandler.d.ts +0 -34
- package/dist/core/handlers/ClickHandler.js +0 -359
- package/dist/core/handlers/ClickHandler.js.map +0 -1
- package/dist/core/handlers/CustomCodeHandler.d.ts +0 -35
- package/dist/core/handlers/CustomCodeHandler.js +0 -102
- package/dist/core/handlers/CustomCodeHandler.js.map +0 -1
- package/dist/core/handlers/DropdownHandler.d.ts +0 -43
- package/dist/core/handlers/DropdownHandler.js +0 -304
- package/dist/core/handlers/DropdownHandler.js.map +0 -1
- package/dist/core/handlers/InputHandler.d.ts +0 -24
- package/dist/core/handlers/InputHandler.js +0 -197
- package/dist/core/handlers/InputHandler.js.map +0 -1
- package/dist/core/registry/ActionRegistry.d.ts +0 -8
- package/dist/core/registry/ActionRegistry.js +0 -35
- package/dist/core/registry/ActionRegistry.js.map +0 -1
- package/dist/installer/frameworkLauncher.d.ts +0 -31
- package/dist/installer/frameworkLauncher.js +0 -198
- package/dist/installer/frameworkLauncher.js.map +0 -1
- package/dist/queue/ExecutionQueue.d.ts +0 -52
- package/dist/queue/ExecutionQueue.js +0 -175
- package/dist/queue/ExecutionQueue.js.map +0 -1
- package/dist/routes/api.routes.d.ts +0 -2
- package/dist/routes/api.routes.js +0 -16
- package/dist/routes/api.routes.js.map +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +0 -30
- package/dist/server.js.map +0 -1
- package/dist/types/types.d.ts +0 -135
- package/dist/types/types.js +0 -4
- package/dist/types/types.js.map +0 -1
- package/dist/utils/elementHighlight.d.ts +0 -35
- package/dist/utils/elementHighlight.js +0 -136
- package/dist/utils/elementHighlight.js.map +0 -1
- package/dist/utils/locatorHelper.d.ts +0 -7
- package/dist/utils/locatorHelper.js +0 -53
- package/dist/utils/locatorHelper.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -12
- package/dist/utils/logger.js +0 -35
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/response.d.ts +0 -4
- package/dist/utils/response.js +0 -25
- package/dist/utils/response.js.map +0 -1
- package/dist/utils/responseFormatter.d.ts +0 -78
- package/dist/utils/responseFormatter.js +0 -123
- package/dist/utils/responseFormatter.js.map +0 -1
- package/dist/utils/sseManager.d.ts +0 -32
- package/dist/utils/sseManager.js +0 -122
- package/dist/utils/sseManager.js.map +0 -1
- package/lexxit-automation-framework-2.0.0.tgz +0 -0
- package/npmignore +0 -5
- package/scripts/postinstall.js +0 -52
- package/src/app.ts +0 -27
- package/src/controllers/controller.ts +0 -282
- package/src/core/BrowserManager.ts +0 -398
- package/src/core/PlaywrightEngine.ts +0 -371
- package/src/core/ScreenshotManager.ts +0 -25
- package/src/core/TestData.ts +0 -25
- package/src/core/TestExecutor.ts +0 -436
- package/src/core/handlers/AllHandlers.ts +0 -626
- package/src/core/handlers/BaseHandler.ts +0 -41
- package/src/core/handlers/ClickHandler.ts +0 -482
- package/src/core/handlers/CustomCodeHandler.ts +0 -123
- package/src/core/handlers/DropdownHandler.ts +0 -438
- package/src/core/handlers/InputHandler.ts +0 -192
- package/src/core/registry/ActionRegistry.ts +0 -31
- package/src/installer/frameworkLauncher.ts +0 -242
- package/src/installer/install.sh +0 -107
- package/src/public/dashboard.html +0 -540
- package/src/public/queue-monitor.html +0 -190
- package/src/queue/ExecutionQueue.ts +0 -200
- package/src/routes/api.routes.ts +0 -16
- package/src/server.ts +0 -29
- package/src/types/types.ts +0 -169
- package/src/utils/elementHighlight.ts +0 -174
- package/src/utils/locatorHelper.ts +0 -49
- package/src/utils/logger.ts +0 -40
- package/src/utils/response.ts +0 -27
- package/src/utils/responseFormatter.ts +0 -167
- package/src/utils/sseManager.ts +0 -127
- package/tsconfig.json +0 -18
- package/videos/fb1b94b6-6639-4c9a-82bb-63572606f403/page@5bd5c6c8b62baa700e9810cdd64f5c49.webm +0 -0
|
@@ -1,626 +0,0 @@
|
|
|
1
|
-
import { Page } from "playwright";
|
|
2
|
-
import { ActionResponse, TestCaseConfig } from "../../types/types";
|
|
3
|
-
import { pass, fail } from "../../utils/response";
|
|
4
|
-
import { buildLocatorString } from "../../utils/locatorHelper";
|
|
5
|
-
import { BaseHandler } from "./BaseHandler";
|
|
6
|
-
|
|
7
|
-
// ─── AssertionHandler ─────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
export class AssertionHandler extends BaseHandler {
|
|
10
|
-
constructor(tConfig: TestCaseConfig, page: Page) { super(tConfig, page); }
|
|
11
|
-
|
|
12
|
-
getActions() {
|
|
13
|
-
return {
|
|
14
|
-
verifytext: this.verifyText.bind(this),
|
|
15
|
-
verifytextcontains: this.verifyTextContains.bind(this),
|
|
16
|
-
verifytextnotequal: this.verifyTextNotEqual.bind(this),
|
|
17
|
-
verifyvalue: this.verifyValue.bind(this),
|
|
18
|
-
verifyvisible: this.verifyVisible.bind(this),
|
|
19
|
-
verifyhidden: this.verifyHidden.bind(this),
|
|
20
|
-
verifyenabled: this.verifyEnabled.bind(this),
|
|
21
|
-
verifydisabled: this.verifyDisabled.bind(this),
|
|
22
|
-
verifyurl: this.verifyURL.bind(this),
|
|
23
|
-
verifypartialurl: this.verifyPartialURL.bind(this),
|
|
24
|
-
verifyelementcount: this.verifyElementCount.bind(this),
|
|
25
|
-
verifyattribute: this.verifyAttribute.bind(this),
|
|
26
|
-
verifychecked: this.verifyChecked.bind(this),
|
|
27
|
-
verifyunchecked: this.verifyUnchecked.bind(this),
|
|
28
|
-
gettext: this.getText.bind(this),
|
|
29
|
-
getattribute: this.getAttribute.bind(this),
|
|
30
|
-
assertequal: this.assertEqual.bind(this),
|
|
31
|
-
assertnotequal: this.assertNotEqual.bind(this),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async verifyText(args: string[]): Promise<ActionResponse> {
|
|
36
|
-
const [strategy, locator, expected] = args;
|
|
37
|
-
if (!strategy || !locator || expected === undefined) return fail("verifyText needs: strategy, locator, expectedText");
|
|
38
|
-
try {
|
|
39
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
40
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
41
|
-
const actual = (await el.innerText()).trim();
|
|
42
|
-
const ok = actual === expected.trim();
|
|
43
|
-
const msg = ok ? `Text matches: "${expected}"` : `Text mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
44
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
45
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
46
|
-
} catch (error: any) {
|
|
47
|
-
return fail(`Failed verifyText [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async verifyTextContains(args: string[]): Promise<ActionResponse> {
|
|
52
|
-
const [strategy, locator, partial] = args;
|
|
53
|
-
if (!strategy || !locator || partial === undefined) return fail("verifyTextContains needs: strategy, locator, partialText");
|
|
54
|
-
try {
|
|
55
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
56
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
57
|
-
const actual = (await el.innerText()).trim();
|
|
58
|
-
const ok = actual.toLowerCase().includes(partial.toLowerCase());
|
|
59
|
-
const msg = ok ? `Text contains: "${partial}"` : `Text "${actual}" does not contain "${partial}"`;
|
|
60
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
61
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
62
|
-
} catch (error: any) {
|
|
63
|
-
return fail(`Failed verifyTextContains [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async verifyTextNotEqual(args: string[]): Promise<ActionResponse> {
|
|
68
|
-
const [strategy, locator, notExpected] = args;
|
|
69
|
-
if (!strategy || !locator || notExpected === undefined) return fail("verifyTextNotEqual needs: strategy, locator, text");
|
|
70
|
-
try {
|
|
71
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
72
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
73
|
-
const actual = (await el.innerText()).trim();
|
|
74
|
-
const ok = actual !== notExpected.trim();
|
|
75
|
-
const msg = ok ? `Text is not "${notExpected}" ✓` : `Text should not equal "${notExpected}"`;
|
|
76
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
77
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
78
|
-
} catch (error: any) {
|
|
79
|
-
return fail(`Failed verifyTextNotEqual [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async verifyValue(args: string[]): Promise<ActionResponse> {
|
|
84
|
-
const [strategy, locator, expected] = args;
|
|
85
|
-
if (!strategy || !locator || expected === undefined) return fail("verifyValue needs: strategy, locator, expected");
|
|
86
|
-
try {
|
|
87
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
88
|
-
await el.waitFor({ state: "attached", timeout: this.timeout });
|
|
89
|
-
const actual = await el.inputValue();
|
|
90
|
-
const ok = actual === expected;
|
|
91
|
-
const msg = ok ? `Value matches: "${expected}"` : `Value mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
92
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
93
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
94
|
-
} catch (error: any) {
|
|
95
|
-
return fail(`Failed verifyValue [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async verifyVisible(args: string[]): Promise<ActionResponse> {
|
|
100
|
-
const [strategy, locator] = args;
|
|
101
|
-
if (!strategy || !locator) return fail("verifyVisible needs: strategy, locator");
|
|
102
|
-
try {
|
|
103
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
104
|
-
const visible = await el.isVisible();
|
|
105
|
-
const msg = visible ? "Element is visible ✓" : "Element is NOT visible";
|
|
106
|
-
const sc = visible ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
107
|
-
return visible ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
108
|
-
} catch (error: any) {
|
|
109
|
-
return fail(`Failed verifyVisible [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async verifyHidden(args: string[]): Promise<ActionResponse> {
|
|
114
|
-
const [strategy, locator] = args;
|
|
115
|
-
if (!strategy || !locator) return fail("verifyHidden needs: strategy, locator");
|
|
116
|
-
try {
|
|
117
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
118
|
-
const hidden = await el.isHidden();
|
|
119
|
-
const msg = hidden ? "Element is hidden ✓" : "Element is visible (expected hidden)";
|
|
120
|
-
const sc = hidden ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
121
|
-
return hidden ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
122
|
-
} catch (error: any) {
|
|
123
|
-
return fail(`Failed verifyHidden [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async verifyEnabled(args: string[]): Promise<ActionResponse> {
|
|
128
|
-
const [strategy, locator] = args;
|
|
129
|
-
if (!strategy || !locator) return fail("verifyEnabled needs: strategy, locator");
|
|
130
|
-
try {
|
|
131
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
132
|
-
const enabled = await el.isEnabled();
|
|
133
|
-
const sc = enabled ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
134
|
-
return enabled ? pass("Element is enabled ✓", sc) : fail("Element is NOT enabled", undefined, sc);
|
|
135
|
-
} catch (error: any) {
|
|
136
|
-
return fail(`Failed verifyEnabled [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async verifyDisabled(args: string[]): Promise<ActionResponse> {
|
|
141
|
-
const [strategy, locator] = args;
|
|
142
|
-
if (!strategy || !locator) return fail("verifyDisabled needs: strategy, locator");
|
|
143
|
-
try {
|
|
144
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
145
|
-
const disabled = await el.isDisabled();
|
|
146
|
-
const sc = disabled ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
147
|
-
return disabled ? pass("Element is disabled ✓", sc) : fail("Element is NOT disabled", undefined, sc);
|
|
148
|
-
} catch (error: any) {
|
|
149
|
-
return fail(`Failed verifyDisabled [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async verifyURL(args: string[]): Promise<ActionResponse> {
|
|
154
|
-
const [expected] = args;
|
|
155
|
-
const actual = this.page.url();
|
|
156
|
-
const ok = actual === expected;
|
|
157
|
-
const msg = ok ? `URL matches ✓` : `URL mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
158
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
159
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async verifyPartialURL(args: string[]): Promise<ActionResponse> {
|
|
163
|
-
const [partial] = args;
|
|
164
|
-
const actual = this.page.url();
|
|
165
|
-
const ok = actual.includes(partial);
|
|
166
|
-
const msg = ok ? `URL contains: "${partial}" ✓` : `URL "${actual}" does not contain "${partial}"`;
|
|
167
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
168
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
async verifyElementCount(args: string[]): Promise<ActionResponse> {
|
|
172
|
-
const [strategy, locator, expectedStr] = args;
|
|
173
|
-
const expected = parseInt(expectedStr, 10);
|
|
174
|
-
if (!strategy || !locator || isNaN(expected)) return fail("verifyElementCount needs: strategy, locator, expectedCount");
|
|
175
|
-
try {
|
|
176
|
-
const actual = await this.page.locator(buildLocatorString(strategy, locator)).count();
|
|
177
|
-
const ok = actual === expected;
|
|
178
|
-
const msg = ok ? `Count: ${actual} ✓` : `Count mismatch. Expected: ${expected}, Got: ${actual}`;
|
|
179
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
180
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
181
|
-
} catch (error: any) {
|
|
182
|
-
return fail(`Failed verifyElementCount [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
async verifyAttribute(args: string[]): Promise<ActionResponse> {
|
|
187
|
-
const [strategy, locator, attribute, expected] = args;
|
|
188
|
-
if (!strategy || !locator || !attribute || expected === undefined) return fail("verifyAttribute needs: strategy, locator, attribute, expectedValue");
|
|
189
|
-
try {
|
|
190
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
191
|
-
await el.waitFor({ state: "attached", timeout: this.timeout });
|
|
192
|
-
const actual = await el.getAttribute(attribute);
|
|
193
|
-
const ok = actual === expected;
|
|
194
|
-
const msg = ok ? `Attribute "${attribute}" = "${expected}" ✓` : `Attr "${attribute}" mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
195
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
196
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
197
|
-
} catch (error: any) {
|
|
198
|
-
return fail(`Failed verifyAttribute [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
async verifyChecked(args: string[]): Promise<ActionResponse> {
|
|
203
|
-
const [strategy, locator] = args;
|
|
204
|
-
if (!strategy || !locator) return fail("verifyChecked needs: strategy, locator");
|
|
205
|
-
try {
|
|
206
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
207
|
-
const checked = await el.isChecked();
|
|
208
|
-
const sc = checked ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
209
|
-
return checked ? pass("Checkbox is checked ✓", sc) : fail("Checkbox is NOT checked", undefined, sc);
|
|
210
|
-
} catch (error: any) {
|
|
211
|
-
return fail(`Failed verifyChecked [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
async verifyUnchecked(args: string[]): Promise<ActionResponse> {
|
|
216
|
-
const [strategy, locator] = args;
|
|
217
|
-
if (!strategy || !locator) return fail("verifyUnchecked needs: strategy, locator");
|
|
218
|
-
try {
|
|
219
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
220
|
-
const unchecked = !(await el.isChecked());
|
|
221
|
-
const sc = unchecked ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
222
|
-
return unchecked ? pass("Checkbox is unchecked ✓", sc) : fail("Checkbox IS checked (expected unchecked)", undefined, sc);
|
|
223
|
-
} catch (error: any) {
|
|
224
|
-
return fail(`Failed verifyUnchecked [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
async getText(args: string[]): Promise<ActionResponse> {
|
|
229
|
-
const [strategy, locator, storeKey] = args;
|
|
230
|
-
if (!strategy || !locator) return fail("getText needs: strategy, locator, [storeKey]");
|
|
231
|
-
try {
|
|
232
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
233
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
234
|
-
const text = (await el.innerText()).trim();
|
|
235
|
-
if (storeKey) this.testData.set(storeKey, text);
|
|
236
|
-
return pass(`Text: "${text}"`, await this.shots.onPass(this.page), { text });
|
|
237
|
-
} catch (error: any) {
|
|
238
|
-
return fail(`Failed getText [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async getAttribute(args: string[]): Promise<ActionResponse> {
|
|
243
|
-
const [strategy, locator, attribute, storeKey] = args;
|
|
244
|
-
if (!strategy || !locator || !attribute) return fail("getAttribute needs: strategy, locator, attribute, [storeKey]");
|
|
245
|
-
try {
|
|
246
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
247
|
-
await el.waitFor({ state: "attached", timeout: this.timeout });
|
|
248
|
-
const value = await el.getAttribute(attribute);
|
|
249
|
-
if (storeKey) this.testData.set(storeKey, value);
|
|
250
|
-
return pass(`Attribute "${attribute}": "${value}"`, await this.shots.onPass(this.page), { value });
|
|
251
|
-
} catch (error: any) {
|
|
252
|
-
return fail(`Failed getAttribute [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
async assertEqual(args: string[]): Promise<ActionResponse> {
|
|
257
|
-
const [actual, expected, label] = args;
|
|
258
|
-
const ok = actual === expected;
|
|
259
|
-
const tag = label || "Value";
|
|
260
|
-
const msg = ok ? `${tag} matches: "${expected}" ✓` : `${tag} mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
261
|
-
return ok ? pass(msg) : fail(msg);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async assertNotEqual(args: string[]): Promise<ActionResponse> {
|
|
265
|
-
const [actual, notExpected, label] = args;
|
|
266
|
-
const ok = actual !== notExpected;
|
|
267
|
-
const tag = label || "Value";
|
|
268
|
-
const msg = ok ? `${tag} is not "${notExpected}" ✓` : `${tag} should not equal "${notExpected}"`;
|
|
269
|
-
return ok ? pass(msg) : fail(msg);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// ─── WaitHandler ─────────────────────────────────────────────────────────────
|
|
274
|
-
|
|
275
|
-
export class WaitHandler extends BaseHandler {
|
|
276
|
-
constructor(tConfig: TestCaseConfig, page: Page) { super(tConfig, page); }
|
|
277
|
-
|
|
278
|
-
getActions() {
|
|
279
|
-
return {
|
|
280
|
-
waitforelement: this.waitForElement.bind(this),
|
|
281
|
-
waitforelementhidden: this.waitForElementHidden.bind(this),
|
|
282
|
-
waitforurl: this.waitForURL.bind(this),
|
|
283
|
-
waitfortitle: this.waitForTitle.bind(this),
|
|
284
|
-
waitforpageload: this.waitForPageLoad.bind(this),
|
|
285
|
-
waitfornetworkidle: this.waitForNetworkIdle.bind(this),
|
|
286
|
-
waitfortextpresent: this.waitForTextPresent.bind(this),
|
|
287
|
-
sleep: this.sleep.bind(this),
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
async waitForElement(args: string[]): Promise<ActionResponse> {
|
|
292
|
-
const [strategy, locator, timeoutStr] = args;
|
|
293
|
-
const timeout = parseInt(timeoutStr || String(this.timeout), 10);
|
|
294
|
-
if (!strategy || !locator) return fail("waitForElement needs: strategy, locator, [timeoutMs]");
|
|
295
|
-
try {
|
|
296
|
-
await this.page.locator(buildLocatorString(strategy, locator)).waitFor({ state: "visible", timeout });
|
|
297
|
-
return pass(`Element visible: [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
298
|
-
} catch (error: any) {
|
|
299
|
-
return fail(`Element not visible in ${timeout}ms [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async waitForElementHidden(args: string[]): Promise<ActionResponse> {
|
|
304
|
-
const [strategy, locator, timeoutStr] = args;
|
|
305
|
-
const timeout = parseInt(timeoutStr || String(this.timeout), 10);
|
|
306
|
-
if (!strategy || !locator) return fail("waitForElementHidden needs: strategy, locator, [timeoutMs]");
|
|
307
|
-
try {
|
|
308
|
-
await this.page.locator(buildLocatorString(strategy, locator)).waitFor({ state: "hidden", timeout });
|
|
309
|
-
return pass(`Element hidden: [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
310
|
-
} catch (error: any) {
|
|
311
|
-
return fail(`Element still visible after ${timeout}ms [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async waitForURL(args: string[]): Promise<ActionResponse> {
|
|
316
|
-
const [urlPattern, timeoutStr] = args;
|
|
317
|
-
const timeout = parseInt(timeoutStr || String(this.timeout), 10);
|
|
318
|
-
if (!urlPattern) return fail("waitForURL needs: urlPattern, [timeoutMs]");
|
|
319
|
-
try {
|
|
320
|
-
await this.page.waitForURL(new RegExp(urlPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")), { timeout });
|
|
321
|
-
return pass(`URL matches: "${urlPattern}"`, await this.shots.onPass(this.page));
|
|
322
|
-
} catch (error: any) {
|
|
323
|
-
return fail(`URL not reached in ${timeout}ms: "${urlPattern}"`, error.message, await this.shots.onFail(this.page));
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
async waitForTitle(args: string[]): Promise<ActionResponse> {
|
|
328
|
-
const [titlePart, timeoutStr] = args;
|
|
329
|
-
const timeout = parseInt(timeoutStr || String(this.timeout), 10);
|
|
330
|
-
if (!titlePart) return fail("waitForTitle needs: titlePart, [timeoutMs]");
|
|
331
|
-
try {
|
|
332
|
-
await this.page.waitForFunction((t: string) => document.title.includes(t), titlePart, { timeout });
|
|
333
|
-
return pass(`Title contains: "${titlePart}"`, await this.shots.onPass(this.page));
|
|
334
|
-
} catch (error: any) {
|
|
335
|
-
return fail(`Title not found in ${timeout}ms: "${titlePart}"`, error.message, await this.shots.onFail(this.page));
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
async waitForPageLoad(args: string[]): Promise<ActionResponse> {
|
|
340
|
-
const timeout = parseInt(args[0] || String(this.timeout), 10);
|
|
341
|
-
try {
|
|
342
|
-
await this.page.waitForLoadState("domcontentloaded", { timeout });
|
|
343
|
-
return pass("Page loaded", await this.shots.onPass(this.page));
|
|
344
|
-
} catch (error: any) {
|
|
345
|
-
return fail(`Page did not load in ${timeout}ms`, error.message, await this.shots.onFail(this.page));
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async waitForNetworkIdle(args: string[]): Promise<ActionResponse> {
|
|
350
|
-
const timeout = parseInt(args[0] || String(this.timeout), 10);
|
|
351
|
-
try {
|
|
352
|
-
await this.page.waitForLoadState("networkidle", { timeout });
|
|
353
|
-
return pass("Network is idle", await this.shots.onPass(this.page));
|
|
354
|
-
} catch (error: any) {
|
|
355
|
-
return fail(`Network not idle in ${timeout}ms`, error.message, await this.shots.onFail(this.page));
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
async waitForTextPresent(args: string[]): Promise<ActionResponse> {
|
|
360
|
-
const [strategy, locator, text, timeoutStr] = args;
|
|
361
|
-
const timeout = parseInt(timeoutStr || String(this.timeout), 10);
|
|
362
|
-
if (!strategy || !locator || !text) return fail("waitForTextPresent needs: strategy, locator, text, [timeoutMs]");
|
|
363
|
-
try {
|
|
364
|
-
await this.page.locator(buildLocatorString(strategy, locator)).filter({ hasText: text }).waitFor({ state: "visible", timeout });
|
|
365
|
-
return pass(`Text "${text}" is present`, await this.shots.onPass(this.page));
|
|
366
|
-
} catch (error: any) {
|
|
367
|
-
return fail(`Text "${text}" not found in ${timeout}ms`, error.message, await this.shots.onFail(this.page));
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
async sleep(args: string[]): Promise<ActionResponse> {
|
|
372
|
-
const ms = parseInt(args[0] || "1000", 10);
|
|
373
|
-
await this.page.waitForTimeout(ms);
|
|
374
|
-
return pass(`Waited ${ms}ms`);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// ─── KeyboardHandler ──────────────────────────────────────────────────────────
|
|
379
|
-
|
|
380
|
-
export class KeyboardHandler extends BaseHandler {
|
|
381
|
-
constructor(tConfig: TestCaseConfig, page: Page) { super(tConfig, page); }
|
|
382
|
-
|
|
383
|
-
getActions() {
|
|
384
|
-
return {
|
|
385
|
-
presskey: this.pressKey.bind(this),
|
|
386
|
-
presskeyon: this.pressKeyOn.bind(this),
|
|
387
|
-
keysendenter: this.sendEnter.bind(this),
|
|
388
|
-
keysendtab: this.sendTab.bind(this),
|
|
389
|
-
keysendesc: this.sendEsc.bind(this),
|
|
390
|
-
keycombo: this.keyCombo.bind(this),
|
|
391
|
-
selectall: this.selectAll.bind(this),
|
|
392
|
-
copytext: this.copyText.bind(this),
|
|
393
|
-
pastetext: this.pasteText.bind(this),
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
async pressKey(args: string[]): Promise<ActionResponse> {
|
|
398
|
-
const [key] = args;
|
|
399
|
-
if (!key) return fail("pressKey needs: keyName (e.g. Enter, Tab, F5, ArrowDown)");
|
|
400
|
-
try {
|
|
401
|
-
await this.page.keyboard.press(key);
|
|
402
|
-
return pass(`Pressed: ${key}`);
|
|
403
|
-
} catch (error: any) {
|
|
404
|
-
return fail(`Failed pressKey: ${key}`, error.message);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
async pressKeyOn(args: string[]): Promise<ActionResponse> {
|
|
409
|
-
const [strategy, locator, key] = args;
|
|
410
|
-
if (!strategy || !locator || !key) return fail("pressKeyOn needs: strategy, locator, keyName");
|
|
411
|
-
try {
|
|
412
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
413
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
414
|
-
await el.press(key, { timeout: this.timeout });
|
|
415
|
-
return pass(`Pressed ${key} on [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
416
|
-
} catch (error: any) {
|
|
417
|
-
return fail(`Failed pressKeyOn [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
async sendEnter(args: string[]): Promise<ActionResponse> { return this.pressKeyOn([args[0], args[1], "Enter"]); }
|
|
422
|
-
async sendTab(args: string[]): Promise<ActionResponse> { return this.pressKeyOn([args[0], args[1], "Tab"]); }
|
|
423
|
-
async sendEsc(args: string[]): Promise<ActionResponse> { return this.pressKeyOn([args[0], args[1], "Escape"]); }
|
|
424
|
-
|
|
425
|
-
// tSetup.keyCombo('Control+A')
|
|
426
|
-
async keyCombo(args: string[]): Promise<ActionResponse> {
|
|
427
|
-
const [combo] = args;
|
|
428
|
-
if (!combo) return fail("keyCombo needs: combo (e.g. Control+A, Control+Shift+T)");
|
|
429
|
-
try {
|
|
430
|
-
await this.page.keyboard.press(combo);
|
|
431
|
-
return pass(`Key combo: ${combo}`);
|
|
432
|
-
} catch (error: any) {
|
|
433
|
-
return fail(`Failed keyCombo: ${combo}`, error.message);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
async selectAll(args: string[]): Promise<ActionResponse> {
|
|
438
|
-
const [strategy, locator] = args;
|
|
439
|
-
try {
|
|
440
|
-
if (strategy && locator) {
|
|
441
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
442
|
-
await el.focus();
|
|
443
|
-
}
|
|
444
|
-
await this.page.keyboard.press("Control+A");
|
|
445
|
-
return pass("Select All (Ctrl+A)");
|
|
446
|
-
} catch (error: any) {
|
|
447
|
-
return fail("Failed selectAll", error.message);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
async copyText(args: string[]): Promise<ActionResponse> {
|
|
452
|
-
try {
|
|
453
|
-
await this.page.keyboard.press("Control+C");
|
|
454
|
-
return pass("Copied selection");
|
|
455
|
-
} catch (error: any) {
|
|
456
|
-
return fail("Failed copyText", error.message);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
async pasteText(args: string[]): Promise<ActionResponse> {
|
|
461
|
-
try {
|
|
462
|
-
await this.page.keyboard.press("Control+V");
|
|
463
|
-
return pass("Pasted");
|
|
464
|
-
} catch (error: any) {
|
|
465
|
-
return fail("Failed pasteText", error.message);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// ─── CheckboxHandler ──────────────────────────────────────────────────────────
|
|
471
|
-
|
|
472
|
-
export class CheckboxHandler extends BaseHandler {
|
|
473
|
-
constructor(tConfig: TestCaseConfig, page: Page) { super(tConfig, page); }
|
|
474
|
-
|
|
475
|
-
getActions() {
|
|
476
|
-
return {
|
|
477
|
-
checkcheckbox: this.check.bind(this),
|
|
478
|
-
uncheckcheckbox: this.uncheck.bind(this),
|
|
479
|
-
togglecheckbox: this.toggle.bind(this),
|
|
480
|
-
selectradio: this.selectRadio.bind(this),
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
async check(args: string[]): Promise<ActionResponse> {
|
|
485
|
-
const [strategy, locator] = args;
|
|
486
|
-
if (!strategy || !locator) return fail("checkCheckbox needs: strategy, locator");
|
|
487
|
-
try {
|
|
488
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
489
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
490
|
-
await el.check({ timeout: this.timeout });
|
|
491
|
-
return pass(`Checked [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
492
|
-
} catch (error: any) {
|
|
493
|
-
return fail(`Failed check [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
async uncheck(args: string[]): Promise<ActionResponse> {
|
|
498
|
-
const [strategy, locator] = args;
|
|
499
|
-
if (!strategy || !locator) return fail("uncheckCheckbox needs: strategy, locator");
|
|
500
|
-
try {
|
|
501
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
502
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
503
|
-
await el.uncheck({ timeout: this.timeout });
|
|
504
|
-
return pass(`Unchecked [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
505
|
-
} catch (error: any) {
|
|
506
|
-
return fail(`Failed uncheck [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
async toggle(args: string[]): Promise<ActionResponse> {
|
|
511
|
-
const [strategy, locator] = args;
|
|
512
|
-
if (!strategy || !locator) return fail("toggleCheckbox needs: strategy, locator");
|
|
513
|
-
try {
|
|
514
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
515
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
516
|
-
const checked = await el.isChecked();
|
|
517
|
-
checked ? await el.uncheck() : await el.check();
|
|
518
|
-
return pass(`Toggled (now ${!checked}) [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
519
|
-
} catch (error: any) {
|
|
520
|
-
return fail(`Failed toggle [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
async selectRadio(args: string[]): Promise<ActionResponse> {
|
|
525
|
-
const [strategy, locator] = args;
|
|
526
|
-
if (!strategy || !locator) return fail("selectRadio needs: strategy, locator");
|
|
527
|
-
try {
|
|
528
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
529
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
530
|
-
await el.click({ timeout: this.timeout });
|
|
531
|
-
return pass(`Radio selected [${strategy}=${locator}]`, await this.shots.onPass(this.page));
|
|
532
|
-
} catch (error: any) {
|
|
533
|
-
return fail(`Failed selectRadio [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// ─── TableHandler ─────────────────────────────────────────────────────────────
|
|
539
|
-
|
|
540
|
-
export class TableHandler extends BaseHandler {
|
|
541
|
-
constructor(tConfig: TestCaseConfig, page: Page) { super(tConfig, page); }
|
|
542
|
-
|
|
543
|
-
getActions() {
|
|
544
|
-
return {
|
|
545
|
-
gettablerowcount: this.getTableRowCount.bind(this),
|
|
546
|
-
gettablecellvalue: this.getTableCellValue.bind(this),
|
|
547
|
-
verifytablecell: this.verifyTableCell.bind(this),
|
|
548
|
-
clicktablerow: this.clickTableRow.bind(this),
|
|
549
|
-
gettablecolumnvalues: this.getTableColumnValues.bind(this),
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// tSetup.getTableRowCount('xpath', '//table/tbody/tr', 'storeKey')
|
|
554
|
-
async getTableRowCount(args: string[]): Promise<ActionResponse> {
|
|
555
|
-
const [strategy, locator, storeKey] = args;
|
|
556
|
-
if (!strategy || !locator) return fail("getTableRowCount needs: strategy, locator, [storeKey]");
|
|
557
|
-
try {
|
|
558
|
-
const count = await this.page.locator(buildLocatorString(strategy, locator)).count();
|
|
559
|
-
if (storeKey) this.testData.set(storeKey, count);
|
|
560
|
-
return pass(`Row count: ${count}`, await this.shots.onPass(this.page), { count });
|
|
561
|
-
} catch (error: any) {
|
|
562
|
-
return fail(`Failed getTableRowCount [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// tSetup.getTableCellValue('xpath', '//table/tbody/tr[2]/td[3]', 'storeKey')
|
|
567
|
-
async getTableCellValue(args: string[]): Promise<ActionResponse> {
|
|
568
|
-
const [strategy, locator, storeKey] = args;
|
|
569
|
-
if (!strategy || !locator) return fail("getTableCellValue needs: strategy, locator, [storeKey]");
|
|
570
|
-
try {
|
|
571
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
572
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
573
|
-
const text = (await el.innerText()).trim();
|
|
574
|
-
if (storeKey) this.testData.set(storeKey, text);
|
|
575
|
-
return pass(`Cell value: "${text}"`, await this.shots.onPass(this.page), { text });
|
|
576
|
-
} catch (error: any) {
|
|
577
|
-
return fail(`Failed getTableCellValue [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// tSetup.verifyTableCell('xpath', '//table/tbody/tr[1]/td[2]', 'Expected Value')
|
|
582
|
-
async verifyTableCell(args: string[]): Promise<ActionResponse> {
|
|
583
|
-
const [strategy, locator, expected] = args;
|
|
584
|
-
if (!strategy || !locator || !expected) return fail("verifyTableCell needs: strategy, locator, expectedValue");
|
|
585
|
-
try {
|
|
586
|
-
const el = this.page.locator(buildLocatorString(strategy, locator));
|
|
587
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
588
|
-
const actual = (await el.innerText()).trim();
|
|
589
|
-
const ok = actual === expected.trim();
|
|
590
|
-
const msg = ok ? `Cell matches: "${expected}" ✓` : `Cell mismatch. Expected: "${expected}", Got: "${actual}"`;
|
|
591
|
-
const sc = ok ? await this.shots.onPass(this.page) : await this.shots.onFail(this.page);
|
|
592
|
-
return ok ? pass(msg, sc) : fail(msg, undefined, sc);
|
|
593
|
-
} catch (error: any) {
|
|
594
|
-
return fail(`Failed verifyTableCell [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// tSetup.clickTableRow('xpath', '//table/tbody/tr', '3')
|
|
599
|
-
async clickTableRow(args: string[]): Promise<ActionResponse> {
|
|
600
|
-
const [strategy, locator, rowStr] = args;
|
|
601
|
-
const row = parseInt(rowStr || "1", 10) - 1;
|
|
602
|
-
if (!strategy || !locator) return fail("clickTableRow needs: strategy, locator, rowNumber");
|
|
603
|
-
try {
|
|
604
|
-
const el = this.page.locator(buildLocatorString(strategy, locator)).nth(row);
|
|
605
|
-
await el.waitFor({ state: "visible", timeout: this.timeout });
|
|
606
|
-
await el.click({ timeout: this.timeout });
|
|
607
|
-
return pass(`Clicked row ${row + 1}`, await this.shots.onPass(this.page));
|
|
608
|
-
} catch (error: any) {
|
|
609
|
-
return fail(`Failed clickTableRow row=${row + 1}`, error.message, await this.shots.onFail(this.page));
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// tSetup.getTableColumnValues('xpath', '//table/tbody/tr/td[2]', 'storeKey')
|
|
614
|
-
async getTableColumnValues(args: string[]): Promise<ActionResponse> {
|
|
615
|
-
const [strategy, locator, storeKey] = args;
|
|
616
|
-
if (!strategy || !locator) return fail("getTableColumnValues needs: strategy, locator, [storeKey]");
|
|
617
|
-
try {
|
|
618
|
-
const values = await this.page.locator(buildLocatorString(strategy, locator)).allInnerTexts();
|
|
619
|
-
const trimmed = values.map(v => v.trim());
|
|
620
|
-
if (storeKey) this.testData.set(storeKey, trimmed);
|
|
621
|
-
return pass(`Column values: [${trimmed.join(", ")}]`, await this.shots.onPass(this.page), { values: trimmed });
|
|
622
|
-
} catch (error: any) {
|
|
623
|
-
return fail(`Failed getTableColumnValues [${strategy}=${locator}]`, error.message, await this.shots.onFail(this.page));
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Page } from "playwright";
|
|
2
|
-
import { TestCaseConfig, IActionHandler, ActionHandler } from "../../types/types";
|
|
3
|
-
import { ScreenshotManager } from "../ScreenshotManager";
|
|
4
|
-
import { Logger } from "../../utils/logger";
|
|
5
|
-
import { highlightElement, removeHighlight } from "../../utils/elementHighlight";
|
|
6
|
-
|
|
7
|
-
export abstract class BaseHandler implements IActionHandler {
|
|
8
|
-
protected page: Page;
|
|
9
|
-
protected testData: TestCaseConfig["testData"];
|
|
10
|
-
protected timeout: number;
|
|
11
|
-
readonly shots: ScreenshotManager;
|
|
12
|
-
protected log: Logger;
|
|
13
|
-
|
|
14
|
-
constructor(tConfig: TestCaseConfig, page: Page) {
|
|
15
|
-
this.page = page;
|
|
16
|
-
this.testData = tConfig.testData;
|
|
17
|
-
this.timeout = tConfig.timeout ?? 30000;
|
|
18
|
-
this.shots = new ScreenshotManager(tConfig.screenshot_mode);
|
|
19
|
-
this.log = Logger.create(this.constructor.name, tConfig.executionId);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
setPage(page: Page): void { this.page = page; }
|
|
23
|
-
|
|
24
|
-
// ── Visual highlight helpers ─────────────────────────────────────────────────
|
|
25
|
-
// Call highlight() BEFORE the interaction, remove() AFTER (pass or fail).
|
|
26
|
-
// All errors are suppressed — highlighting is purely cosmetic.
|
|
27
|
-
|
|
28
|
-
protected async highlight(
|
|
29
|
-
locatorStr: string,
|
|
30
|
-
type: "input" | "click" | "verify" | "select" | "checkbox" = "input",
|
|
31
|
-
label: string = "",
|
|
32
|
-
): Promise<void> {
|
|
33
|
-
await highlightElement(this.page, locatorStr, type, label);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
protected async unhighlight(): Promise<void> {
|
|
37
|
-
await removeHighlight(this.page);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
abstract getActions(): Record<string, ActionHandler>;
|
|
41
|
-
}
|