lexxit-automation-framework 2.0.19 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -57
- package/npmignore +8 -0
- package/package.json +32 -1
- package/public/dashboard.html +591 -0
- package/src/actions/baseHandler.ts +351 -0
- package/src/actions/browserManager.ts +432 -0
- package/src/actions/checkboxHandler.ts +276 -0
- package/src/actions/clickHandler.ts +513 -0
- package/src/actions/customcodehandler.ts +251 -0
- package/src/actions/dropdownHandler.ts +501 -0
- package/src/actions/radiobuttonHandler.ts +286 -0
- package/src/actions/textHandler.ts +498 -0
- package/src/api/server.ts +210 -0
- package/src/config.ts +7 -0
- package/src/executor/functionMap.ts +153 -0
- package/src/executor/mapping.ts +70 -0
- package/src/executor/scriptExecutor.ts +162 -0
- package/src/executor/stepExecutor.ts +289 -0
- package/src/runner/testRunner.ts +78 -0
- package/src/sse/sseManager.ts +130 -0
- package/src/store/executionStore.ts +152 -0
- package/src/store/testDataStore.ts +46 -0
- package/src/types/types.ts +159 -0
- package/src/utils/healingService.ts +210 -0
- package/src/utils/locatorService.ts +73 -0
- package/src/utils/logger.ts +27 -0
- package/src/utils/metadataService.ts +137 -0
- package/src/utils/waitConditions.ts +141 -0
- package/src/validator/validator.ts +140 -0
- package/tsconfig.json +16 -0
- package/bin/lexxit-automation-framework.js +0 -224
- package/dist-obf/app.js +0 -1
- package/dist-obf/controllers/controller.js +0 -1
- package/dist-obf/core/BrowserManager.js +0 -1
- package/dist-obf/core/PlaywrightEngine.js +0 -1
- package/dist-obf/core/ScreenshotManager.js +0 -1
- package/dist-obf/core/TestData.js +0 -1
- package/dist-obf/core/TestExecutor.js +0 -1
- package/dist-obf/core/handlers/AllHandlers.js +0 -1
- package/dist-obf/core/handlers/BaseHandler.js +0 -1
- package/dist-obf/core/handlers/ClickHandler.js +0 -1
- package/dist-obf/core/handlers/CustomCodeHandler.js +0 -1
- package/dist-obf/core/handlers/DropdownHandler.js +0 -1
- package/dist-obf/core/handlers/InputHandler.js +0 -1
- package/dist-obf/core/registry/ActionRegistry.js +0 -1
- package/dist-obf/installer/frameworkLauncher.js +0 -1
- package/dist-obf/public/dashboard.html +0 -591
- package/dist-obf/public/execution.html +0 -510
- package/dist-obf/public/queue-monitor.html +0 -408
- package/dist-obf/queue/ExecutionQueue.js +0 -1
- package/dist-obf/routes/api.routes.js +0 -1
- package/dist-obf/server.js +0 -1
- package/dist-obf/types/types.js +0 -1
- package/dist-obf/utils/chromefinder.js +0 -1
- package/dist-obf/utils/elementHighlight.js +0 -1
- package/dist-obf/utils/locatorHelper.js +0 -1
- package/dist-obf/utils/logger.js +0 -1
- package/dist-obf/utils/response.js +0 -1
- package/dist-obf/utils/responseFormatter.js +0 -1
- package/dist-obf/utils/sseManager.js +0 -1
- package/scripts/postinstall.js +0 -52
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { Page } from 'playwright';
|
|
2
|
+
import { ScreenshotMode, StepResult} from '../types/types';
|
|
3
|
+
import { LocatorService } from '../utils/locatorService';
|
|
4
|
+
import { BaseHandler } from './baseHandler';
|
|
5
|
+
import { DEFAULT_SCREENSHOT_MODE } from '../config';
|
|
6
|
+
|
|
7
|
+
export class CheckboxHandler extends BaseHandler {
|
|
8
|
+
protected page: Page;
|
|
9
|
+
|
|
10
|
+
constructor(page: Page, screenshotMode: ScreenshotMode = DEFAULT_SCREENSHOT_MODE) {
|
|
11
|
+
super();
|
|
12
|
+
this.page = page;
|
|
13
|
+
this.screenshotMode = screenshotMode;
|
|
14
|
+
this.setupNetworkCapture(page);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// // ─── Helpers ───────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
// private getStartTime(): string {
|
|
20
|
+
// return new Date().toISOString();
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// private getDuration(startMs: number): number {
|
|
24
|
+
// return Date.now() - startMs;
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
// private buildResult(
|
|
28
|
+
// status: 'PASS' | 'FAIL',
|
|
29
|
+
// expected_result: string,
|
|
30
|
+
// comments: string,
|
|
31
|
+
// startMs: number,
|
|
32
|
+
// startTime: string,
|
|
33
|
+
// step_name: string = '',
|
|
34
|
+
// uid: string | null = null,
|
|
35
|
+
// obj_uid: string | null = null,
|
|
36
|
+
// page_uid: string | null = null
|
|
37
|
+
// ): StepResult {
|
|
38
|
+
// return {
|
|
39
|
+
// uid,
|
|
40
|
+
// obj_uid,
|
|
41
|
+
// page_uid,
|
|
42
|
+
// step_name,
|
|
43
|
+
// step_script: '',
|
|
44
|
+
// status,
|
|
45
|
+
// expected_result,
|
|
46
|
+
// comments,
|
|
47
|
+
// duration: this.getDuration(startMs),
|
|
48
|
+
// start_time: startTime
|
|
49
|
+
// };
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// private async captureScreenshot(isFailure: boolean): Promise<string | undefined> {
|
|
53
|
+
// if (this.screenshotMode === 'never') return undefined;
|
|
54
|
+
// if (this.screenshotMode === 'on_failure' && !isFailure) return undefined;
|
|
55
|
+
// try {
|
|
56
|
+
// if (!this.page || this.page.isClosed()) return undefined;
|
|
57
|
+
// const buf = await this.page.screenshot({ type: 'png', fullPage: false });
|
|
58
|
+
// return buf.toString('base64');
|
|
59
|
+
// } catch {
|
|
60
|
+
// return undefined;
|
|
61
|
+
// }
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
// private classifyError(error: any): string {
|
|
65
|
+
// const msg: string = error?.message || String(error);
|
|
66
|
+
|
|
67
|
+
// if (msg.includes('Element not found') || msg.includes('not visible')) {
|
|
68
|
+
// return `Element not found or not visible: ${msg}`;
|
|
69
|
+
// }
|
|
70
|
+
// if (msg.includes('Timeout') || msg.includes('timeout')) {
|
|
71
|
+
// return `Timeout error - element took too long to respond: ${msg}`;
|
|
72
|
+
// }
|
|
73
|
+
// if (msg.includes('not enabled')) {
|
|
74
|
+
// return `Element is disabled: ${msg}`;
|
|
75
|
+
// }
|
|
76
|
+
// if (msg.includes('detached')) {
|
|
77
|
+
// return `Element got detached from DOM: ${msg}`;
|
|
78
|
+
// }
|
|
79
|
+
// if (msg.includes('Target closed') || msg.includes('has been closed')) {
|
|
80
|
+
// return `Browser or page closed unexpectedly: ${msg}`;
|
|
81
|
+
// }
|
|
82
|
+
// if (msg.includes('intercepts pointer events')) {
|
|
83
|
+
// return `Element is covered by another element: ${msg}`;
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// return `Unexpected error: ${msg}`;
|
|
87
|
+
// }
|
|
88
|
+
|
|
89
|
+
// private appendMatchedLocatorInfo(comments: string, matchedIndex: number, matchedXPath: string): string {
|
|
90
|
+
// if (matchedIndex > 0) {
|
|
91
|
+
// return `${comments} (Matched locator at position ${matchedIndex}: ${matchedXPath})`;
|
|
92
|
+
// }
|
|
93
|
+
// return comments;
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
// ─── check ─────────────────────────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
async check(label: string, locators: string[], step_name: string = 'Check checkbox'): Promise<StepResult> {
|
|
99
|
+
const startMs = Date.now();
|
|
100
|
+
const startTime = this.getStartTime();
|
|
101
|
+
const expected = `'${label}' checked successfully`;
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
105
|
+
await resolved.element.check();
|
|
106
|
+
|
|
107
|
+
const comments = this.appendMatchedLocatorInfo(expected, resolved.matchedIndex, resolved.matchedXPath);
|
|
108
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
109
|
+
} catch (error: any) {
|
|
110
|
+
// const sc = await this.captureScreenshot(true);
|
|
111
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ─── uncheck ───────────────────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
async uncheck(label: string, locators: string[], step_name: string = 'Uncheck checkbox'): Promise<StepResult> {
|
|
118
|
+
const startMs = Date.now();
|
|
119
|
+
const startTime = this.getStartTime();
|
|
120
|
+
const expected = `'${label}' unchecked successfully`;
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
124
|
+
await resolved.element.uncheck();
|
|
125
|
+
|
|
126
|
+
const comments = this.appendMatchedLocatorInfo(expected, resolved.matchedIndex, resolved.matchedXPath);
|
|
127
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
128
|
+
} catch (error: any) {
|
|
129
|
+
// const sc = await this.captureScreenshot(true);
|
|
130
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ─── toggle ────────────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
async toggle(label: string, locators: string[], step_name: string = 'Toggle checkbox'): Promise<StepResult> {
|
|
137
|
+
const startMs = Date.now();
|
|
138
|
+
const startTime = this.getStartTime();
|
|
139
|
+
const expected = `'${label}' toggled successfully`;
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
143
|
+
const isChecked = await resolved.element.isChecked();
|
|
144
|
+
|
|
145
|
+
if (isChecked) {
|
|
146
|
+
await resolved.element.uncheck();
|
|
147
|
+
} else {
|
|
148
|
+
await resolved.element.check();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const comments = this.appendMatchedLocatorInfo(expected, resolved.matchedIndex, resolved.matchedXPath);
|
|
152
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
153
|
+
} catch (error: any) {
|
|
154
|
+
// const sc = await this.captureScreenshot(true);
|
|
155
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ─── isChecked ─────────────────────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
async isChecked(label: string, locators: string[], step_name: string = 'Check if checkbox is checked'): Promise<StepResult> {
|
|
162
|
+
const startMs = Date.now();
|
|
163
|
+
const startTime = this.getStartTime();
|
|
164
|
+
const expected = `'${label}' checked state retrieved successfully`;
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
168
|
+
const checked = await resolved.element.isChecked();
|
|
169
|
+
|
|
170
|
+
const comments = this.appendMatchedLocatorInfo(
|
|
171
|
+
`'${label}' is ${checked ? 'checked' : 'unchecked'}`,
|
|
172
|
+
resolved.matchedIndex,
|
|
173
|
+
resolved.matchedXPath
|
|
174
|
+
);
|
|
175
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
176
|
+
} catch (error: any) {
|
|
177
|
+
// const sc = await this.captureScreenshot(true);
|
|
178
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ─── verifyChecked ─────────────────────────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
async verifyChecked(label: string, locators: string[], step_name: string = 'Verify checkbox is checked'): Promise<StepResult> {
|
|
185
|
+
const startMs = Date.now();
|
|
186
|
+
const startTime = this.getStartTime();
|
|
187
|
+
const expected = `'${label}' is checked`;
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
191
|
+
const checked = await resolved.element.isChecked();
|
|
192
|
+
|
|
193
|
+
if (!checked) {
|
|
194
|
+
const failComments = this.appendMatchedLocatorInfo(`'${label}' is not checked`, resolved.matchedIndex, resolved.matchedXPath);
|
|
195
|
+
// const sc = await this.captureScreenshot(true);
|
|
196
|
+
return this.buildResult('FAIL', expected, failComments, startMs, startTime, step_name);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const comments = this.appendMatchedLocatorInfo(expected, resolved.matchedIndex, resolved.matchedXPath);
|
|
200
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
201
|
+
} catch (error: any) {
|
|
202
|
+
// const sc = await this.captureScreenshot(true);
|
|
203
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ─── verifyUnchecked ───────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
async verifyUnchecked(label: string, locators: string[], step_name: string = 'Verify checkbox is unchecked'): Promise<StepResult> {
|
|
210
|
+
const startMs = Date.now();
|
|
211
|
+
const startTime = this.getStartTime();
|
|
212
|
+
const expected = `'${label}' is unchecked`;
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
216
|
+
const checked = await resolved.element.isChecked();
|
|
217
|
+
|
|
218
|
+
if (checked) {
|
|
219
|
+
const failComments = this.appendMatchedLocatorInfo(`'${label}' is checked`, resolved.matchedIndex, resolved.matchedXPath);
|
|
220
|
+
// const sc = await this.captureScreenshot(true);
|
|
221
|
+
return this.buildResult('FAIL', expected, failComments, startMs, startTime, step_name);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const comments = this.appendMatchedLocatorInfo(expected, resolved.matchedIndex, resolved.matchedXPath);
|
|
225
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
226
|
+
} catch (error: any) {
|
|
227
|
+
// const sc = await this.captureScreenshot(true);
|
|
228
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ─── isEnabled ─────────────────────────────────────────────────────────────
|
|
233
|
+
|
|
234
|
+
async isEnabled(label: string, locators: string[], step_name: string = 'Check if checkbox is enabled'): Promise<StepResult> {
|
|
235
|
+
const startMs = Date.now();
|
|
236
|
+
const startTime = this.getStartTime();
|
|
237
|
+
const expected = `'${label}' enabled state retrieved successfully`;
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
241
|
+
const enabled = await resolved.element.isEnabled();
|
|
242
|
+
|
|
243
|
+
const comments = this.appendMatchedLocatorInfo(
|
|
244
|
+
`'${label}' is ${enabled ? 'enabled' : 'disabled'}`,
|
|
245
|
+
resolved.matchedIndex,
|
|
246
|
+
resolved.matchedXPath
|
|
247
|
+
);
|
|
248
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
249
|
+
} catch (error: any) {
|
|
250
|
+
// const sc = await this.captureScreenshot(true);
|
|
251
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ─── isVisible ─────────────────────────────────────────────────────────────
|
|
256
|
+
|
|
257
|
+
async isVisible(label: string, locators: string[], step_name: string = 'Check if checkbox is visible'): Promise<StepResult> {
|
|
258
|
+
const startMs = Date.now();
|
|
259
|
+
const startTime = this.getStartTime();
|
|
260
|
+
const expected = `'${label}' visibility state retrieved successfully`;
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
const resolved = await LocatorService.resolveElement(this.page, locators);
|
|
264
|
+
const visible = await resolved.element.isVisible();
|
|
265
|
+
|
|
266
|
+
const comments = this.appendMatchedLocatorInfo(
|
|
267
|
+
`'${label}' is ${visible ? 'visible' : 'not visible'}`,
|
|
268
|
+
resolved.matchedIndex,
|
|
269
|
+
resolved.matchedXPath
|
|
270
|
+
);
|
|
271
|
+
return this.buildResult('PASS', expected, comments, startMs, startTime, step_name);
|
|
272
|
+
} catch (error: any) {
|
|
273
|
+
return this.buildResult('FAIL', expected, this.classifyError(error), startMs, startTime, step_name);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|