pw-automation-framework 2.0.1

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 (111) hide show
  1. package/README.md +93 -0
  2. package/bin/lexxit-automation-framework.js +427 -0
  3. package/dist/app.d.ts +2 -0
  4. package/dist/app.js +26 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/controllers/controller.d.ts +57 -0
  7. package/dist/controllers/controller.js +263 -0
  8. package/dist/controllers/controller.js.map +1 -0
  9. package/dist/core/BrowserManager.d.ts +46 -0
  10. package/dist/core/BrowserManager.js +377 -0
  11. package/dist/core/BrowserManager.js.map +1 -0
  12. package/dist/core/PlaywrightEngine.d.ts +16 -0
  13. package/dist/core/PlaywrightEngine.js +246 -0
  14. package/dist/core/PlaywrightEngine.js.map +1 -0
  15. package/dist/core/ScreenshotManager.d.ts +10 -0
  16. package/dist/core/ScreenshotManager.js +28 -0
  17. package/dist/core/ScreenshotManager.js.map +1 -0
  18. package/dist/core/TestData.d.ts +12 -0
  19. package/dist/core/TestData.js +29 -0
  20. package/dist/core/TestData.js.map +1 -0
  21. package/dist/core/TestExecutor.d.ts +16 -0
  22. package/dist/core/TestExecutor.js +355 -0
  23. package/dist/core/TestExecutor.js.map +1 -0
  24. package/dist/core/handlers/AllHandlers.d.ts +116 -0
  25. package/dist/core/handlers/AllHandlers.js +648 -0
  26. package/dist/core/handlers/AllHandlers.js.map +1 -0
  27. package/dist/core/handlers/BaseHandler.d.ts +16 -0
  28. package/dist/core/handlers/BaseHandler.js +27 -0
  29. package/dist/core/handlers/BaseHandler.js.map +1 -0
  30. package/dist/core/handlers/ClickHandler.d.ts +34 -0
  31. package/dist/core/handlers/ClickHandler.js +359 -0
  32. package/dist/core/handlers/ClickHandler.js.map +1 -0
  33. package/dist/core/handlers/CustomCodeHandler.d.ts +35 -0
  34. package/dist/core/handlers/CustomCodeHandler.js +102 -0
  35. package/dist/core/handlers/CustomCodeHandler.js.map +1 -0
  36. package/dist/core/handlers/DropdownHandler.d.ts +43 -0
  37. package/dist/core/handlers/DropdownHandler.js +304 -0
  38. package/dist/core/handlers/DropdownHandler.js.map +1 -0
  39. package/dist/core/handlers/InputHandler.d.ts +24 -0
  40. package/dist/core/handlers/InputHandler.js +197 -0
  41. package/dist/core/handlers/InputHandler.js.map +1 -0
  42. package/dist/core/registry/ActionRegistry.d.ts +8 -0
  43. package/dist/core/registry/ActionRegistry.js +35 -0
  44. package/dist/core/registry/ActionRegistry.js.map +1 -0
  45. package/dist/installer/frameworkLauncher.d.ts +31 -0
  46. package/dist/installer/frameworkLauncher.js +198 -0
  47. package/dist/installer/frameworkLauncher.js.map +1 -0
  48. package/dist/queue/ExecutionQueue.d.ts +52 -0
  49. package/dist/queue/ExecutionQueue.js +175 -0
  50. package/dist/queue/ExecutionQueue.js.map +1 -0
  51. package/dist/routes/api.routes.d.ts +2 -0
  52. package/dist/routes/api.routes.js +16 -0
  53. package/dist/routes/api.routes.js.map +1 -0
  54. package/dist/server.d.ts +1 -0
  55. package/dist/server.js +30 -0
  56. package/dist/server.js.map +1 -0
  57. package/dist/types/types.d.ts +135 -0
  58. package/dist/types/types.js +4 -0
  59. package/dist/types/types.js.map +1 -0
  60. package/dist/utils/elementHighlight.d.ts +35 -0
  61. package/dist/utils/elementHighlight.js +136 -0
  62. package/dist/utils/elementHighlight.js.map +1 -0
  63. package/dist/utils/locatorHelper.d.ts +7 -0
  64. package/dist/utils/locatorHelper.js +53 -0
  65. package/dist/utils/locatorHelper.js.map +1 -0
  66. package/dist/utils/logger.d.ts +12 -0
  67. package/dist/utils/logger.js +35 -0
  68. package/dist/utils/logger.js.map +1 -0
  69. package/dist/utils/response.d.ts +4 -0
  70. package/dist/utils/response.js +25 -0
  71. package/dist/utils/response.js.map +1 -0
  72. package/dist/utils/responseFormatter.d.ts +78 -0
  73. package/dist/utils/responseFormatter.js +123 -0
  74. package/dist/utils/responseFormatter.js.map +1 -0
  75. package/dist/utils/sseManager.d.ts +32 -0
  76. package/dist/utils/sseManager.js +122 -0
  77. package/dist/utils/sseManager.js.map +1 -0
  78. package/lexxit-automation-framework-2.0.0.tgz +0 -0
  79. package/npmignore +5 -0
  80. package/package.json +36 -0
  81. package/scripts/postinstall.js +52 -0
  82. package/src/app.ts +27 -0
  83. package/src/controllers/controller.ts +282 -0
  84. package/src/core/BrowserManager.ts +398 -0
  85. package/src/core/PlaywrightEngine.ts +371 -0
  86. package/src/core/ScreenshotManager.ts +25 -0
  87. package/src/core/TestData.ts +25 -0
  88. package/src/core/TestExecutor.ts +436 -0
  89. package/src/core/handlers/AllHandlers.ts +626 -0
  90. package/src/core/handlers/BaseHandler.ts +41 -0
  91. package/src/core/handlers/ClickHandler.ts +482 -0
  92. package/src/core/handlers/CustomCodeHandler.ts +123 -0
  93. package/src/core/handlers/DropdownHandler.ts +438 -0
  94. package/src/core/handlers/InputHandler.ts +192 -0
  95. package/src/core/registry/ActionRegistry.ts +31 -0
  96. package/src/installer/frameworkLauncher.ts +242 -0
  97. package/src/installer/install.sh +107 -0
  98. package/src/public/dashboard.html +540 -0
  99. package/src/public/queue-monitor.html +190 -0
  100. package/src/queue/ExecutionQueue.ts +200 -0
  101. package/src/routes/api.routes.ts +16 -0
  102. package/src/server.ts +29 -0
  103. package/src/types/types.ts +169 -0
  104. package/src/utils/elementHighlight.ts +174 -0
  105. package/src/utils/locatorHelper.ts +49 -0
  106. package/src/utils/logger.ts +40 -0
  107. package/src/utils/response.ts +27 -0
  108. package/src/utils/responseFormatter.ts +167 -0
  109. package/src/utils/sseManager.ts +127 -0
  110. package/tsconfig.json +18 -0
  111. package/videos/fb1b94b6-6639-4c9a-82bb-63572606f403/page@5bd5c6c8b62baa700e9810cdd64f5c49.webm +0 -0
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executionQueue = exports.ExecutionQueue = void 0;
4
+ const uuid_1 = require("uuid");
5
+ const TestExecutor_1 = require("../core/TestExecutor");
6
+ const sseManager_1 = require("../utils/sseManager");
7
+ const logger_1 = require("../utils/logger");
8
+ const log = logger_1.Logger.create("ExecutionQueue");
9
+ class ExecutionQueue {
10
+ constructor(maxConcurrent = 3) {
11
+ this.jobs = new Map();
12
+ this.running = new Set();
13
+ this.maxConcurrent = maxConcurrent;
14
+ }
15
+ // ─── Enqueue ───────────────────────────────────────────────────────────────
16
+ enqueue(payload) {
17
+ const executionId = (0, uuid_1.v4)();
18
+ const job = {
19
+ executionId,
20
+ status: "queued",
21
+ payload,
22
+ queuedAt: new Date().toISOString(),
23
+ cancelRequested: false,
24
+ progress: {
25
+ total_scripts: payload.scripts.length,
26
+ completed_scripts: 0,
27
+ total_steps: payload.scripts.reduce((s, sc) => s + sc.steps.length, 0),
28
+ completed_steps: 0,
29
+ passed_steps: 0,
30
+ failed_steps: 0,
31
+ skipped_steps: 0,
32
+ },
33
+ };
34
+ this.jobs.set(executionId, job);
35
+ log.info(`Queued: ${executionId} | scripts=${payload.scripts.length}`);
36
+ this.broadcastQueueUpdate();
37
+ this.processNext();
38
+ return executionId;
39
+ }
40
+ // ─── Cancel ────────────────────────────────────────────────────────────────
41
+ cancel(executionId) {
42
+ const job = this.jobs.get(executionId);
43
+ if (!job)
44
+ return { success: false, message: "Execution not found" };
45
+ if (job.status === "done" || job.status === "failed" || job.status === "cancelled") {
46
+ return { success: false, message: `Cannot cancel — already ${job.status}` };
47
+ }
48
+ job.cancelRequested = true;
49
+ if (job.status === "queued") {
50
+ // Not started yet — cancel immediately
51
+ job.status = "cancelled";
52
+ job.cancelledAt = new Date().toISOString();
53
+ sseManager_1.sseManager.emit(executionId, "execution_cancelled", {
54
+ message: "Execution cancelled before it started",
55
+ executionId,
56
+ });
57
+ this.broadcastQueueUpdate();
58
+ log.info(`Cancelled (queued): ${executionId}`);
59
+ return { success: true, message: "Execution cancelled" };
60
+ }
61
+ // Running — signal the executor to stop after current step
62
+ log.info(`Cancel requested (running): ${executionId}`);
63
+ sseManager_1.sseManager.emit(executionId, "log", {
64
+ message: "⏹ Cancellation requested — stopping after current step...",
65
+ });
66
+ return { success: true, message: "Cancellation requested — will stop after current step" };
67
+ }
68
+ // ─── Cancel All ────────────────────────────────────────────────────────────
69
+ cancelAll() {
70
+ let count = 0;
71
+ this.jobs.forEach((job) => {
72
+ if (job.status === "queued" || job.status === "running") {
73
+ this.cancel(job.executionId);
74
+ count++;
75
+ }
76
+ });
77
+ return { cancelled: count };
78
+ }
79
+ // ─── Process ───────────────────────────────────────────────────────────────
80
+ processNext() {
81
+ if (this.running.size >= this.maxConcurrent)
82
+ return;
83
+ const next = Array.from(this.jobs.values()).find(j => j.status === "queued");
84
+ if (!next)
85
+ return;
86
+ this.running.add(next.executionId);
87
+ next.status = "running";
88
+ next.startedAt = new Date().toISOString();
89
+ this.broadcastQueueUpdate();
90
+ this.runJob(next).catch((err) => {
91
+ log.error(`Job crashed: ${next.executionId} — ${err.message}`);
92
+ next.status = "failed";
93
+ next.error = err.message;
94
+ this.finalize(next.executionId);
95
+ });
96
+ }
97
+ async runJob(job) {
98
+ log.info(`Starting: ${job.executionId}`);
99
+ try {
100
+ const result = await TestExecutor_1.TestExecutor.run(job.payload, job.executionId,
101
+ // Progress callback
102
+ (update) => {
103
+ Object.assign(job.progress, update);
104
+ this.broadcastQueueUpdate();
105
+ },
106
+ // Cancel check — TestExecutor polls this
107
+ () => job.cancelRequested);
108
+ if (job.cancelRequested) {
109
+ job.status = "cancelled";
110
+ job.cancelledAt = new Date().toISOString();
111
+ }
112
+ else {
113
+ job.result = result;
114
+ job.status = result.overall_status === "PASS" ? "done" : "failed";
115
+ }
116
+ job.completedAt = new Date().toISOString();
117
+ }
118
+ catch (error) {
119
+ job.status = "failed";
120
+ job.error = error.message;
121
+ job.completedAt = new Date().toISOString();
122
+ sseManager_1.sseManager.emit(job.executionId, "error", { message: error.message });
123
+ }
124
+ this.finalize(job.executionId);
125
+ }
126
+ finalize(executionId) {
127
+ this.running.delete(executionId);
128
+ this.broadcastQueueUpdate();
129
+ log.info(`Finalized: ${executionId} | running=${this.running.size}/${this.maxConcurrent}`);
130
+ // Keep jobs in memory 1 hour for replay
131
+ setTimeout(() => this.jobs.delete(executionId), 60 * 60 * 1000);
132
+ this.processNext();
133
+ }
134
+ // ─── Query ─────────────────────────────────────────────────────────────────
135
+ getJob(executionId) {
136
+ return this.jobs.get(executionId);
137
+ }
138
+ isCancelRequested(executionId) {
139
+ return this.jobs.get(executionId)?.cancelRequested ?? false;
140
+ }
141
+ getAllJobs() {
142
+ return Array.from(this.jobs.values())
143
+ .sort((a, b) => new Date(b.queuedAt).getTime() - new Date(a.queuedAt).getTime());
144
+ }
145
+ getQueueStats() {
146
+ const jobs = this.getAllJobs();
147
+ return {
148
+ total: jobs.length,
149
+ queued: jobs.filter(j => j.status === "queued").length,
150
+ running: jobs.filter(j => j.status === "running").length,
151
+ done: jobs.filter(j => j.status === "done").length,
152
+ failed: jobs.filter(j => j.status === "failed").length,
153
+ cancelled: jobs.filter(j => j.status === "cancelled").length,
154
+ maxConcurrent: this.maxConcurrent,
155
+ jobs: jobs.map(j => ({
156
+ executionId: j.executionId,
157
+ status: j.status,
158
+ queuedAt: j.queuedAt,
159
+ startedAt: j.startedAt,
160
+ completedAt: j.completedAt,
161
+ cancelledAt: j.cancelledAt,
162
+ progress: j.progress,
163
+ error: j.error,
164
+ overall_status: j.result?.overall_status,
165
+ cancelRequested: j.cancelRequested,
166
+ })),
167
+ };
168
+ }
169
+ broadcastQueueUpdate() {
170
+ sseManager_1.sseManager.broadcast("queue_update", this.getQueueStats());
171
+ }
172
+ }
173
+ exports.ExecutionQueue = ExecutionQueue;
174
+ exports.executionQueue = new ExecutionQueue(3);
175
+ //# sourceMappingURL=ExecutionQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionQueue.js","sourceRoot":"","sources":["../../src/queue/ExecutionQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const express_1 = require("express");
4
+ const controller_1 = require("../controllers/controller");
5
+ const router = (0, express_1.Router)();
6
+ router.post("/run-test", controller_1.ApiController.runTest);
7
+ router.get("/stream/:executionId", controller_1.ApiController.stream);
8
+ router.get("/result/:executionId", controller_1.ApiController.getResult); // ← full formatted result
9
+ router.get("/status/:executionId", controller_1.ApiController.getStatus); // ← lightweight status
10
+ router.delete("/cancel/:executionId", controller_1.ApiController.cancelExecution);
11
+ router.delete("/cancel-all", controller_1.ApiController.cancelAll);
12
+ router.get("/queue", controller_1.ApiController.getQueue);
13
+ router.get("/actions", controller_1.ApiController.listActions);
14
+ router.get("/health", controller_1.ApiController.health);
15
+ exports.default = router;
16
+ //# sourceMappingURL=api.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.routes.js","sourceRoot":"","sources":["../../src/routes/api.routes.ts"],"names":[],"mappings":";;AAAA,qCAAiC;AACjC,0DAA0D;AAE1D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,IAAI,CAAG,WAAW,EAAe,0BAAa,CAAC,OAAO,CAAC,CAAC;AAC/D,MAAM,CAAC,GAAG,CAAI,sBAAsB,EAAI,0BAAa,CAAC,MAAM,CAAC,CAAC;AAC9D,MAAM,CAAC,GAAG,CAAI,sBAAsB,EAAI,0BAAa,CAAC,SAAS,CAAC,CAAC,CAAI,0BAA0B;AAC/F,MAAM,CAAC,GAAG,CAAI,sBAAsB,EAAI,0BAAa,CAAC,SAAS,CAAC,CAAC,CAAI,uBAAuB;AAC5F,MAAM,CAAC,MAAM,CAAC,sBAAsB,EAAI,0BAAa,CAAC,eAAe,CAAC,CAAC;AACvE,MAAM,CAAC,MAAM,CAAC,aAAa,EAAa,0BAAa,CAAC,SAAS,CAAC,CAAC;AACjE,MAAM,CAAC,GAAG,CAAI,QAAQ,EAAkB,0BAAa,CAAC,QAAQ,CAAC,CAAC;AAChE,MAAM,CAAC,GAAG,CAAI,UAAU,EAAgB,0BAAa,CAAC,WAAW,CAAC,CAAC;AACnE,MAAM,CAAC,GAAG,CAAI,SAAS,EAAiB,0BAAa,CAAC,MAAM,CAAC,CAAC;AAE9D,kBAAe,MAAM,CAAC"}
@@ -0,0 +1 @@
1
+ import "dotenv/config";
package/dist/server.js ADDED
@@ -0,0 +1,30 @@
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
+ require("dotenv/config");
7
+ const app_1 = __importDefault(require("./app"));
8
+ const PORT = parseInt(process.env.PORT || "3000", 10);
9
+ const server = app_1.default.listen(PORT, () => {
10
+ console.log("\n" + "═".repeat(60));
11
+ console.log(" 🎭 Playwright Automation Framework v2.0");
12
+ console.log("═".repeat(60));
13
+ console.log(` API : http://localhost:${PORT}/api`);
14
+ console.log(` Queue Monitor: http://localhost:${PORT}/queue-monitor`);
15
+ console.log(` Health : http://localhost:${PORT}/api/health`);
16
+ console.log(` Actions : http://localhost:${PORT}/api/actions`);
17
+ console.log("═".repeat(60) + "\n");
18
+ });
19
+ server.keepAliveTimeout = 65000;
20
+ server.headersTimeout = 66000;
21
+ const shutdown = (signal) => {
22
+ console.log(`\n[SHUTDOWN] ${signal} received`);
23
+ server.close(() => process.exit(0));
24
+ setTimeout(() => process.exit(1), 10000);
25
+ };
26
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
27
+ process.on("SIGINT", () => shutdown("SIGINT"));
28
+ process.on("uncaughtException", (e) => { console.error("[FATAL]", e); shutdown("uncaughtException"); });
29
+ process.on("unhandledRejection", (r) => console.error("[UNHANDLED]", r));
30
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;AAAA,yBAAuB;AACvB,gDAAwB;AAExB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtD,MAAM,MAAM,GAAG,aAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACnC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,MAAM,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,gBAAgB,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,aAAa,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,cAAc,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC;AAChC,MAAM,CAAC,cAAc,GAAK,KAAK,CAAC;AAEhC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;IAClC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,WAAW,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAa,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC5D,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAc,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC3D,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAG,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzG,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,135 @@
1
+ export type ScreenshotMode = "always" | "on_failure" | "never";
2
+ export type StepStatus = "PASS" | "FAIL" | "SKIP" | "RUNNING" | "PENDING";
3
+ export type ScriptStatus = "PASS" | "FAIL" | "RUNNING" | "PENDING";
4
+ export type QueueStatus = "queued" | "running" | "done" | "failed" | "cancelled";
5
+ export type SSEEventType = "execution_start" | "script_start" | "step_start" | "step_complete" | "script_complete" | "execution_complete" | "execution_cancelled" | "queue_update" | "log" | "error" | "health";
6
+ export interface ITestData {
7
+ set(key: string, value: unknown): void;
8
+ get(key: string): unknown;
9
+ has(key: string): boolean;
10
+ resolve(value: unknown): unknown;
11
+ getAll(): Record<string, unknown>;
12
+ }
13
+ export interface TestCaseConfig {
14
+ testData: ITestData;
15
+ screenshot_mode: ScreenshotMode;
16
+ record_video: boolean;
17
+ headless: boolean;
18
+ executionId: string;
19
+ timeout: number;
20
+ slowMo?: number;
21
+ }
22
+ export interface RequestPayload {
23
+ scripts: Script[];
24
+ stop_on_failure?: boolean;
25
+ parallel?: boolean;
26
+ max_parallel?: number;
27
+ }
28
+ export interface Script {
29
+ test_script_uid: string;
30
+ test_case_name?: string;
31
+ app_id?: string;
32
+ headless?: boolean;
33
+ screenshot_mode?: ScreenshotMode;
34
+ record_video?: boolean;
35
+ stop_on_failure?: boolean;
36
+ steps: Step[];
37
+ browser?: string;
38
+ }
39
+ export interface Step {
40
+ uid?: string;
41
+ step_name: string;
42
+ step_script: string;
43
+ label?: string;
44
+ obj_uid?: string;
45
+ page_uid?: string | null;
46
+ value?: string;
47
+ continue_on_failure?: boolean;
48
+ }
49
+ export interface StepResult {
50
+ uid?: string;
51
+ obj_uid?: string;
52
+ step_name: string;
53
+ step_script?: string;
54
+ status: StepStatus;
55
+ page_uid?: string | null;
56
+ comments: string;
57
+ screenshot?: string;
58
+ duration_ms: number;
59
+ start_time: string;
60
+ expected_result?: string;
61
+ skip_reason?: string;
62
+ label?: string;
63
+ value?: string;
64
+ comparison_code?: any;
65
+ }
66
+ export interface ScriptResult {
67
+ test_script_uid: string;
68
+ test_case_name: string;
69
+ step_results: StepResult[];
70
+ overall_status: ScriptStatus;
71
+ app_id?: string;
72
+ duration_ms: number;
73
+ start_time: string;
74
+ browser?: string;
75
+ passed_steps: number;
76
+ failed_steps: number;
77
+ skipped_steps: number;
78
+ total_steps: number;
79
+ }
80
+ export interface ExecutionResult {
81
+ executionId: string;
82
+ overall_status: "PASS" | "FAIL" | "CANCELLED";
83
+ total_scripts: number;
84
+ passed: number;
85
+ failed: number;
86
+ duration_ms: number;
87
+ results: ScriptResult[];
88
+ }
89
+ export interface QueueJob {
90
+ executionId: string;
91
+ status: QueueStatus;
92
+ payload: RequestPayload;
93
+ queuedAt: string;
94
+ startedAt?: string;
95
+ completedAt?: string;
96
+ cancelledAt?: string;
97
+ result?: ExecutionResult;
98
+ error?: string;
99
+ cancelRequested: boolean;
100
+ progress: {
101
+ total_scripts: number;
102
+ completed_scripts: number;
103
+ total_steps: number;
104
+ completed_steps: number;
105
+ passed_steps: number;
106
+ failed_steps: number;
107
+ skipped_steps: number;
108
+ };
109
+ }
110
+ export interface LogEntry {
111
+ level: LogLevel;
112
+ message: string;
113
+ timestamp?: string;
114
+ }
115
+ export interface ActionResponse {
116
+ status: "Pass" | "Fail";
117
+ comments: string;
118
+ screenshot?: string;
119
+ data?: any;
120
+ }
121
+ export interface ParsedStep {
122
+ action: string;
123
+ args: string[];
124
+ }
125
+ export type ActionHandler = (args: string[]) => Promise<ActionResponse | undefined>;
126
+ export interface IActionHandler {
127
+ getActions(): Record<string, ActionHandler>;
128
+ }
129
+ export interface SSEEvent {
130
+ type: SSEEventType;
131
+ executionId: string;
132
+ timestamp: string;
133
+ data: any;
134
+ }
135
+ export type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR";
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ // ─── Enums / Literals ────────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":";AAAA,gFAAgF"}
@@ -0,0 +1,35 @@
1
+ import { Page } from "playwright";
2
+ /**
3
+ * elementHighlight.ts
4
+ * ===================
5
+ * Injects a visual highlight into the browser window BEFORE the framework
6
+ * interacts with an element. This lets the user watching the automation
7
+ * clearly see which field is being targeted.
8
+ *
9
+ * Visual effects:
10
+ * • Glowing border (blue for input/click, orange for verify/assertion)
11
+ * • Ripple pulse animation
12
+ * • Small floating label showing the step action + value
13
+ * • Auto-removes after the interaction completes (or on timeout)
14
+ *
15
+ * Usage (in handlers):
16
+ * await highlightElement(this.page, locatorString, 'input', 'Ravi');
17
+ * // ... do the actual interaction ...
18
+ * await removeHighlight(this.page);
19
+ */
20
+ type HighlightType = "input" | "click" | "verify" | "select" | "checkbox";
21
+ /**
22
+ * Highlights an element in the browser before interacting with it.
23
+ *
24
+ * @param page Playwright Page
25
+ * @param locator CSS/XPath locator string (already built)
26
+ * @param type Visual type: input | click | verify | select | checkbox
27
+ * @param labelText Short text shown in the floating label (e.g. the value being entered)
28
+ */
29
+ export declare function highlightElement(page: Page, locator: string, type?: HighlightType, labelText?: string): Promise<void>;
30
+ /**
31
+ * Removes the visual highlight from the page.
32
+ * Called after the interaction completes (or on failure).
33
+ */
34
+ export declare function removeHighlight(page: Page): Promise<void>;
35
+ export {};
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.highlightElement = highlightElement;
4
+ exports.removeHighlight = removeHighlight;
5
+ const COLORS = {
6
+ input: { border: "#3b82f6", bg: "rgba(59,130,246,0.08)", label: "#3b82f6" },
7
+ click: { border: "#22c55e", bg: "rgba(34,197,94,0.08)", label: "#22c55e" },
8
+ verify: { border: "#a855f7", bg: "rgba(168,85,247,0.08)", label: "#a855f7" },
9
+ select: { border: "#f59e0b", bg: "rgba(245,158,11,0.08)", label: "#f59e0b" },
10
+ checkbox: { border: "#ec4899", bg: "rgba(236,72,153,0.08)", label: "#ec4899" },
11
+ };
12
+ /**
13
+ * Highlights an element in the browser before interacting with it.
14
+ *
15
+ * @param page Playwright Page
16
+ * @param locator CSS/XPath locator string (already built)
17
+ * @param type Visual type: input | click | verify | select | checkbox
18
+ * @param labelText Short text shown in the floating label (e.g. the value being entered)
19
+ */
20
+ async function highlightElement(page, locator, type = "input", labelText = "") {
21
+ const c = COLORS[type];
22
+ try {
23
+ await page.evaluate(({ locator, border, bg, labelColor, labelText }) => {
24
+ // ── Find element ──────────────────────────────────────────────────────
25
+ let el = null;
26
+ if (locator.startsWith("//") || locator.startsWith("(//") || locator.startsWith("./")) {
27
+ // XPath
28
+ const result = document.evaluate(locator, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
29
+ el = result.singleNodeValue;
30
+ }
31
+ else {
32
+ // CSS
33
+ try {
34
+ el = document.querySelector(locator);
35
+ }
36
+ catch { /* bad selector */ }
37
+ }
38
+ if (!el || !(el instanceof HTMLElement))
39
+ return;
40
+ // ── Remove any previous highlight ─────────────────────────────────────
41
+ document.querySelectorAll("[data-pw-highlight]").forEach(n => {
42
+ const orig = n.dataset.pwOrigStyle ?? "";
43
+ n.style.cssText = orig;
44
+ delete n.dataset.pwHighlight;
45
+ delete n.dataset.pwOrigStyle;
46
+ });
47
+ document.querySelectorAll("#pw-overlay,#pw-label,#pw-ripple-style").forEach(n => n.remove());
48
+ // ── Store original style ───────────────────────────────────────────────
49
+ el.dataset.pwHighlight = "1";
50
+ el.dataset.pwOrigStyle = el.style.cssText;
51
+ // ── Apply highlight styles ─────────────────────────────────────────────
52
+ el.style.outline = `2px solid ${border}`;
53
+ el.style.outlineOffset = "2px";
54
+ el.style.boxShadow = `0 0 0 4px ${bg}, 0 0 16px ${border}55`;
55
+ el.style.transition = "outline .15s, box-shadow .15s";
56
+ el.style.zIndex = "9999";
57
+ // ── Scroll element into view (smooth) ─────────────────────────────────
58
+ el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
59
+ // ── Ripple pulse animation ─────────────────────────────────────────────
60
+ const style = document.createElement("style");
61
+ style.id = "pw-ripple-style";
62
+ style.textContent = `
63
+ @keyframes pwRipple {
64
+ 0% { box-shadow: 0 0 0 0 ${border}66, 0 0 0 0 ${border}33; }
65
+ 50% { box-shadow: 0 0 0 6px ${border}33, 0 0 0 12px ${border}11; }
66
+ 100% { box-shadow: 0 0 0 0 ${border}00, 0 0 0 0 ${border}00; }
67
+ }
68
+ `;
69
+ document.head.appendChild(style);
70
+ el.style.animation = "pwRipple .7s ease-out";
71
+ // ── Floating label ─────────────────────────────────────────────────────
72
+ if (labelText) {
73
+ const rect = el.getBoundingClientRect();
74
+ const label = document.createElement("div");
75
+ label.id = "pw-label";
76
+ const scrollX = window.scrollX || document.documentElement.scrollLeft;
77
+ const scrollY = window.scrollY || document.documentElement.scrollTop;
78
+ // Position above the element; clamp to viewport
79
+ const top = Math.max(scrollY + rect.top - 36, scrollY + 4);
80
+ const left = Math.min(Math.max(scrollX + rect.left, scrollX + 4), scrollX + document.documentElement.clientWidth - 240);
81
+ Object.assign(label.style, {
82
+ position: "absolute",
83
+ top: `${top}px`,
84
+ left: `${left}px`,
85
+ zIndex: "2147483647",
86
+ background: "#0a0d14",
87
+ color: labelColor,
88
+ border: `1px solid ${border}`,
89
+ borderRadius: "6px",
90
+ padding: "3px 10px",
91
+ fontSize: "12px",
92
+ fontFamily: "-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif",
93
+ fontWeight: "600",
94
+ pointerEvents: "none",
95
+ whiteSpace: "nowrap",
96
+ maxWidth: "260px",
97
+ overflow: "hidden",
98
+ textOverflow: "ellipsis",
99
+ boxShadow: "0 4px 14px rgba(0,0,0,.5)",
100
+ animation: "pwFadeIn .15s ease",
101
+ });
102
+ const styleTag = document.createElement("style");
103
+ styleTag.textContent = "@keyframes pwFadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}";
104
+ document.head.appendChild(styleTag);
105
+ label.textContent = `⚡ ${labelText.length > 40 ? labelText.slice(0, 37) + "…" : labelText}`;
106
+ document.body.appendChild(label);
107
+ }
108
+ }, { locator, border: c.border, bg: c.bg, labelColor: c.label, labelText });
109
+ }
110
+ catch {
111
+ // Highlight is purely cosmetic — never throw
112
+ }
113
+ }
114
+ /**
115
+ * Removes the visual highlight from the page.
116
+ * Called after the interaction completes (or on failure).
117
+ */
118
+ async function removeHighlight(page) {
119
+ try {
120
+ await page.evaluate(() => {
121
+ document.querySelectorAll("[data-pw-highlight]").forEach(n => {
122
+ const el = n;
123
+ el.style.cssText = el.dataset.pwOrigStyle ?? "";
124
+ el.style.animation = "";
125
+ delete el.dataset.pwHighlight;
126
+ delete el.dataset.pwOrigStyle;
127
+ });
128
+ document.querySelectorAll("#pw-overlay,#pw-label,#pw-ripple-style").forEach(n => n.remove());
129
+ document.querySelectorAll("style[textContent*='pwFadeIn'],style[textContent*='pwRipple']").forEach(n => n.remove());
130
+ });
131
+ }
132
+ catch {
133
+ // Cosmetic — never throw
134
+ }
135
+ }
136
+ //# sourceMappingURL=elementHighlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementHighlight.js","sourceRoot":"","sources":["../../src/utils/elementHighlight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * buildLocatorString
3
+ * ==================
4
+ * Converts strategy + value → Playwright selector string.
5
+ * Supports all standard and Playwright-native strategies.
6
+ */
7
+ export declare function buildLocatorString(strategy: string, value: string): string;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildLocatorString = buildLocatorString;
4
+ /**
5
+ * buildLocatorString
6
+ * ==================
7
+ * Converts strategy + value → Playwright selector string.
8
+ * Supports all standard and Playwright-native strategies.
9
+ */
10
+ function buildLocatorString(strategy, value) {
11
+ switch (strategy.toLowerCase().replace(/[_\s-]/g, "")) {
12
+ case "xpath":
13
+ return `xpath=${value}`;
14
+ case "css":
15
+ case "cssselector":
16
+ return value;
17
+ case "id":
18
+ return `#${value}`;
19
+ case "name":
20
+ return `[name="${value}"]`;
21
+ case "placeholder":
22
+ return `[placeholder="${value}"]`;
23
+ case "text":
24
+ case "linktext":
25
+ return `text=${value}`;
26
+ case "partiallinktext":
27
+ case "partialtext":
28
+ return `text=${value}`;
29
+ case "classname":
30
+ case "class":
31
+ return `.${value}`;
32
+ case "tagname":
33
+ case "tag":
34
+ return value;
35
+ case "testid":
36
+ case "datatestid":
37
+ return `[data-testid="${value}"]`;
38
+ case "label":
39
+ return `label=${value}`;
40
+ case "arialabel":
41
+ return `[aria-label="${value}"]`;
42
+ case "role":
43
+ return `[role="${value}"]`;
44
+ case "title":
45
+ return `[title="${value}"]`;
46
+ case "value":
47
+ return `[value="${value}"]`;
48
+ default:
49
+ console.warn(`[WARN] Unknown strategy "${strategy}", treating as CSS`);
50
+ return value;
51
+ }
52
+ }
53
+ //# sourceMappingURL=locatorHelper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locatorHelper.js","sourceRoot":"","sources":["../../src/utils/locatorHelper.ts"],"names":[],"mappings":";;AAMA,gDA0CC;AAhDD;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,QAAgB,EAAE,KAAa;IAChE,QAAQ,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC;QACtD,KAAK,OAAO;YACV,OAAO,SAAS,KAAK,EAAE,CAAC;QAC1B,KAAK,KAAK,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC;QACf,KAAK,IAAI;YACP,OAAO,IAAI,KAAK,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,OAAO,UAAU,KAAK,IAAI,CAAC;QAC7B,KAAK,aAAa;YAChB,OAAO,iBAAiB,KAAK,IAAI,CAAC;QACpC,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU;YACb,OAAO,QAAQ,KAAK,EAAE,CAAC;QACzB,KAAK,iBAAiB,CAAC;QACvB,KAAK,aAAa;YAChB,OAAO,QAAQ,KAAK,EAAE,CAAC;QACzB,KAAK,WAAW,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,IAAI,KAAK,EAAE,CAAC;QACrB,KAAK,SAAS,CAAC;QACf,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY;YACf,OAAO,iBAAiB,KAAK,IAAI,CAAC;QACpC,KAAK,OAAO;YACV,OAAO,SAAS,KAAK,EAAE,CAAC;QAC1B,KAAK,WAAW;YACd,OAAO,gBAAgB,KAAK,IAAI,CAAC;QACnC,KAAK,MAAM;YACT,OAAO,UAAU,KAAK,IAAI,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,WAAW,KAAK,IAAI,CAAC;QAC9B,KAAK,OAAO;YACV,OAAO,WAAW,KAAK,IAAI,CAAC;QAC9B;YACE,OAAO,CAAC,IAAI,CAAC,4BAA4B,QAAQ,oBAAoB,CAAC,CAAC;YACvE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}