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,242 @@
1
+ /**
2
+ * frameworkLauncher.ts
3
+ * ====================
4
+ * Called by your MAIN APP's backend to ensure the framework is running.
5
+ * Handles: health check → install if missing → start → return URL.
6
+ *
7
+ * Usage in your main app's API route:
8
+ * import { ensureFramework, submitExecution } from './frameworkLauncher';
9
+ * const url = await ensureFramework();
10
+ * const run = await submitExecution(payload);
11
+ */
12
+
13
+ import { execFile, exec } from "child_process";
14
+ import { promisify } from "util";
15
+ import path from "path";
16
+ import http from "http";
17
+ import fs from "fs";
18
+
19
+ const execFileAsync = promisify(execFile);
20
+ const execAsync = promisify(exec);
21
+
22
+ const FRAMEWORK_PORT = parseInt(process.env.FRAMEWORK_PORT || "3000", 10);
23
+ const FRAMEWORK_BASE = `http://localhost:${FRAMEWORK_PORT}`;
24
+ const INSTALL_DIR = path.join(
25
+ process.env.HOME || process.env.USERPROFILE || "/tmp",
26
+ ".pw-automation-framework"
27
+ );
28
+ const PID_FILE = path.join(INSTALL_DIR, ".pid");
29
+ const LOG_FILE = path.join(INSTALL_DIR, "server.log");
30
+ const VERSION_FILE = path.join(INSTALL_DIR, "VERSION");
31
+ const CURRENT_VERSION = "2.0.0";
32
+ // ⬇️ Update this to your actual hosted bundle URL
33
+ const BUNDLE_BASE_URL = process.env.FRAMEWORK_BUNDLE_URL || "https://your-registry.example.com/releases";
34
+
35
+ // ─── Health check ─────────────────────────────────────────────────────────────
36
+
37
+ export async function isFrameworkRunning(): Promise<boolean> {
38
+ return new Promise((resolve) => {
39
+ const req = http.get(
40
+ `${FRAMEWORK_BASE}/api/health`,
41
+ { timeout: 800 },
42
+ (res) => resolve(res.statusCode === 200)
43
+ );
44
+ req.on("error", () => resolve(false));
45
+ req.on("timeout", () => { req.destroy(); resolve(false); });
46
+ });
47
+ }
48
+
49
+ export async function getFrameworkVersion(): Promise<string | null> {
50
+ try {
51
+ if (fs.existsSync(VERSION_FILE)) {
52
+ return fs.readFileSync(VERSION_FILE, "utf-8").trim();
53
+ }
54
+ } catch { /* ignore */ }
55
+ return null;
56
+ }
57
+
58
+ // ─── Download & install ───────────────────────────────────────────────────────
59
+
60
+ export async function installFramework(
61
+ onLog?: (msg: string) => void
62
+ ): Promise<void> {
63
+ const log = (msg: string) => { console.log(`[Installer] ${msg}`); onLog?.(msg); };
64
+
65
+ fs.mkdirSync(INSTALL_DIR, { recursive: true });
66
+
67
+ log(`Installing framework v${CURRENT_VERSION} to ${INSTALL_DIR}…`);
68
+
69
+ const bundleURL = `${BUNDLE_BASE_URL}/pw-framework-v${CURRENT_VERSION}.tar.gz`;
70
+ const bundleTmp = path.join(INSTALL_DIR, "bundle.tar.gz");
71
+
72
+ // Download bundle
73
+ log("Downloading framework bundle…");
74
+ await new Promise<void>((resolve, reject) => {
75
+ const file = fs.createWriteStream(bundleTmp);
76
+ http.get(bundleURL.replace("https://", "http://"), (res) => {
77
+ res.pipe(file);
78
+ file.on("finish", () => { file.close(); resolve(); });
79
+ }).on("error", (err) => {
80
+ fs.unlink(bundleTmp, () => {});
81
+ reject(new Error(`Download failed: ${err.message}. \nManually download from: ${bundleURL}`));
82
+ });
83
+ });
84
+
85
+ log("Extracting…");
86
+ await execAsync(`tar -xzf "${bundleTmp}" -C "${INSTALL_DIR}" --strip-components=1`);
87
+ fs.unlinkSync(bundleTmp);
88
+
89
+ log("Installing dependencies (this may take a minute)…");
90
+ await execAsync(`npm install --omit=dev --silent`, { cwd: INSTALL_DIR });
91
+
92
+ log("Installing Playwright browsers…");
93
+ try {
94
+ await execAsync(`npx playwright install chromium --with-deps`, { cwd: INSTALL_DIR });
95
+ } catch {
96
+ await execAsync(`npx playwright install chromium`, { cwd: INSTALL_DIR });
97
+ }
98
+
99
+ // Write version marker
100
+ fs.writeFileSync(VERSION_FILE, CURRENT_VERSION);
101
+ log(`Installation complete ✓`);
102
+ }
103
+
104
+ // ─── Start server ─────────────────────────────────────────────────────────────
105
+
106
+ export async function startFramework(onLog?: (msg: string) => void): Promise<void> {
107
+ const log = (msg: string) => { console.log(`[Launcher] ${msg}`); onLog?.(msg); };
108
+
109
+ log(`Starting framework on port ${FRAMEWORK_PORT}…`);
110
+
111
+ const serverFile = path.join(INSTALL_DIR, "dist", "server.js");
112
+ if (!fs.existsSync(serverFile)) {
113
+ throw new Error(`server.js not found at ${serverFile}. Run installFramework() first.`);
114
+ }
115
+
116
+ // const child = execFile("node", [serverFile], {
117
+ // env: { ...process.env, PORT: String(FRAMEWORK_PORT) },
118
+ // cwd: INSTALL_DIR,
119
+ // detached: true,
120
+ // stdio: ["ignore", fs.openSync(LOG_FILE, "a"), fs.openSync(LOG_FILE, "a")],
121
+ // });
122
+ const child = execFile(
123
+ "node",
124
+ [serverFile],
125
+ {
126
+ env: { ...process.env, PORT: String(FRAMEWORK_PORT) },
127
+ cwd: INSTALL_DIR,
128
+ detached: true,
129
+ stdio: ["ignore", fs.openSync(LOG_FILE, "a"), fs.openSync(LOG_FILE, "a")]
130
+ } as any // 👈 THIS LINE FIXES YOUR ERROR
131
+ );
132
+
133
+ child.unref();
134
+ if (child.pid) fs.writeFileSync(PID_FILE, String(child.pid));
135
+
136
+ // Wait for health (up to 15s)
137
+ for (let i = 0; i < 30; i++) {
138
+ await new Promise(r => setTimeout(r, 500));
139
+ if (await isFrameworkRunning()) {
140
+ log(`Framework ready at ${FRAMEWORK_BASE} ✓`);
141
+ return;
142
+ }
143
+ }
144
+
145
+ throw new Error(`Framework did not start within 15s. Check ${LOG_FILE}`);
146
+ }
147
+
148
+ // ─── Main entry — ensures framework is running ────────────────────────────────
149
+
150
+ export interface EnsureResult {
151
+ baseUrl: string;
152
+ installed: boolean;
153
+ started: boolean;
154
+ version: string;
155
+ }
156
+
157
+ export async function ensureFramework(
158
+ onLog?: (msg: string) => void
159
+ ): Promise<EnsureResult> {
160
+ const log = (msg: string) => { console.log(`[ensureFramework] ${msg}`); onLog?.(msg); };
161
+
162
+ // 1. Already running?
163
+ if (await isFrameworkRunning()) {
164
+ log("Framework already running ✓");
165
+ return { baseUrl: FRAMEWORK_BASE, installed: false, started: false, version: CURRENT_VERSION };
166
+ }
167
+
168
+ // 2. Installed but not running?
169
+ const installedVersion = await getFrameworkVersion();
170
+ let needsInstall = installedVersion !== CURRENT_VERSION;
171
+
172
+ if (needsInstall) {
173
+ log(installedVersion
174
+ ? `Updating from v${installedVersion} → v${CURRENT_VERSION}…`
175
+ : "First install…");
176
+ await installFramework(onLog);
177
+ }
178
+
179
+ // 3. Start
180
+ await startFramework(onLog);
181
+
182
+ return {
183
+ baseUrl: FRAMEWORK_BASE,
184
+ installed: needsInstall,
185
+ started: true,
186
+ version: CURRENT_VERSION,
187
+ };
188
+ }
189
+
190
+ // ─── Submit execution ─────────────────────────────────────────────────────────
191
+
192
+ export async function submitExecution(
193
+ payload: any,
194
+ onLog?: (msg: string) => void
195
+ ): Promise<{ executionId: string; dashboardURL: string; status: string }> {
196
+
197
+ await ensureFramework(onLog);
198
+
199
+ const body = JSON.stringify(payload);
200
+ return new Promise((resolve, reject) => {
201
+ const req = http.request(
202
+ {
203
+ hostname: "localhost",
204
+ port: FRAMEWORK_PORT,
205
+ path: "/api/run-test",
206
+ method: "POST",
207
+ headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) },
208
+ },
209
+ (res) => {
210
+ let data = "";
211
+ res.on("data", c => data += c);
212
+ res.on("end", () => {
213
+ try { resolve(JSON.parse(data)); }
214
+ catch { reject(new Error(`Invalid response: ${data}`)); }
215
+ });
216
+ }
217
+ );
218
+ req.on("error", reject);
219
+ req.write(body);
220
+ req.end();
221
+ });
222
+ }
223
+
224
+ // ─── Cancel execution ─────────────────────────────────────────────────────────
225
+
226
+ export async function cancelExecution(executionId: string): Promise<{ success: boolean; message: string }> {
227
+ return new Promise((resolve, reject) => {
228
+ const req = http.request(
229
+ { hostname: "localhost", port: FRAMEWORK_PORT, path: `/api/cancel/${executionId}`, method: "DELETE" },
230
+ (res) => {
231
+ let data = "";
232
+ res.on("data", c => data += c);
233
+ res.on("end", () => {
234
+ try { resolve(JSON.parse(data)); }
235
+ catch { reject(new Error(`Invalid response: ${data}`)); }
236
+ });
237
+ }
238
+ );
239
+ req.on("error", reject);
240
+ req.end();
241
+ });
242
+ }
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bash
2
+ # ============================================================
3
+ # PW Automation Framework — Auto Installer
4
+ # Triggered from the web UI on first Execute click.
5
+ # Runs silently, installs framework locally, starts server.
6
+ # ============================================================
7
+
8
+ set -e
9
+
10
+ FRAMEWORK_VERSION="2.0.0"
11
+ INSTALL_DIR="$HOME/.pw-automation-framework"
12
+ PORT="${PW_PORT:-3000}"
13
+ PID_FILE="$INSTALL_DIR/.pid"
14
+ LOG_FILE="$INSTALL_DIR/server.log"
15
+ REGISTRY_URL="${PW_REGISTRY_URL:-https://your-registry.example.com/releases}"
16
+
17
+ log() { echo "[$(date '+%H:%M:%S')] $*"; }
18
+
19
+ # ── 1. Check if already running ──────────────────────────────────────────────
20
+ if [ -f "$PID_FILE" ]; then
21
+ PID=$(cat "$PID_FILE")
22
+ if kill -0 "$PID" 2>/dev/null; then
23
+ # Check if it's the right version
24
+ CURRENT_VER=$(curl -s "http://localhost:$PORT/api/health" 2>/dev/null | grep -o '"version":"[^"]*"' | grep -o '[0-9.]*' || echo "")
25
+ if [ "$CURRENT_VER" = "$FRAMEWORK_VERSION" ]; then
26
+ log "Framework v$FRAMEWORK_VERSION already running (PID $PID)"
27
+ echo "RUNNING:$PORT"
28
+ exit 0
29
+ else
30
+ log "Outdated version ($CURRENT_VER) running — upgrading to $FRAMEWORK_VERSION"
31
+ kill "$PID" 2>/dev/null || true
32
+ sleep 1
33
+ fi
34
+ fi
35
+ fi
36
+
37
+ # ── 2. Check Node.js ─────────────────────────────────────────────────────────
38
+ if ! command -v node &>/dev/null; then
39
+ log "ERROR: Node.js not found. Please install Node.js 18+ from https://nodejs.org"
40
+ exit 1
41
+ fi
42
+
43
+ NODE_MAJOR=$(node -e "process.stdout.write(process.version.slice(1).split('.')[0])")
44
+ if [ "$NODE_MAJOR" -lt 18 ]; then
45
+ log "ERROR: Node.js 18+ required. Current: $(node -v)"
46
+ exit 1
47
+ fi
48
+
49
+ log "Node.js $(node -v) ✓"
50
+
51
+ # ── 3. Install / update framework ────────────────────────────────────────────
52
+ mkdir -p "$INSTALL_DIR"
53
+
54
+ INSTALLED_VER=""
55
+ [ -f "$INSTALL_DIR/package.json" ] && \
56
+ INSTALLED_VER=$(node -e "try{process.stdout.write(require('$INSTALL_DIR/package.json').version||'')}catch{}" 2>/dev/null || echo "")
57
+
58
+ if [ "$INSTALLED_VER" != "$FRAMEWORK_VERSION" ]; then
59
+ log "Installing framework v$FRAMEWORK_VERSION → $INSTALL_DIR"
60
+
61
+ # Download release bundle (update URL to your actual hosting)
62
+ BUNDLE_URL="$REGISTRY_URL/pw-framework-v$FRAMEWORK_VERSION.tar.gz"
63
+ BUNDLE_TMP="/tmp/pw-framework-$FRAMEWORK_VERSION.tar.gz"
64
+
65
+ if command -v curl &>/dev/null; then
66
+ curl -fsSL "$BUNDLE_URL" -o "$BUNDLE_TMP"
67
+ elif command -v wget &>/dev/null; then
68
+ wget -q "$BUNDLE_URL" -O "$BUNDLE_TMP"
69
+ else
70
+ log "ERROR: Neither curl nor wget found"
71
+ exit 1
72
+ fi
73
+
74
+ tar -xzf "$BUNDLE_TMP" -C "$INSTALL_DIR" --strip-components=1
75
+ rm -f "$BUNDLE_TMP"
76
+
77
+ cd "$INSTALL_DIR"
78
+ log "Installing npm dependencies…"
79
+ npm install --omit=dev --silent
80
+
81
+ log "Installing Playwright browsers…"
82
+ npx playwright install chromium firefox webkit --with-deps 2>/dev/null || \
83
+ npx playwright install chromium --with-deps 2>/dev/null || true
84
+
85
+ log "Build complete ✓"
86
+ fi
87
+
88
+ # ── 4. Start the server ───────────────────────────────────────────────────────
89
+ cd "$INSTALL_DIR"
90
+ log "Starting framework server on port $PORT…"
91
+
92
+ PORT=$PORT nohup node dist/server.js >> "$LOG_FILE" 2>&1 &
93
+ echo $! > "$PID_FILE"
94
+ log "Server started (PID $(cat $PID_FILE))"
95
+
96
+ # ── 5. Wait for health check ──────────────────────────────────────────────────
97
+ for i in $(seq 1 20); do
98
+ sleep 0.5
99
+ if curl -sf "http://localhost:$PORT/api/health" >/dev/null 2>&1; then
100
+ log "Framework ready at http://localhost:$PORT ✓"
101
+ echo "RUNNING:$PORT"
102
+ exit 0
103
+ fi
104
+ done
105
+
106
+ log "ERROR: Framework did not start within 10 seconds. Check $LOG_FILE"
107
+ exit 1