@reshotdev/screenshot 0.0.1-beta.12 → 0.0.1-beta.13
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 +67 -22
- package/package.json +18 -14
- package/src/commands/auth.js +37 -7
- package/src/commands/capture-dom.js +50 -0
- package/src/commands/compose.js +220 -0
- package/src/commands/doctor-target.js +36 -4
- package/src/commands/drifts.js +13 -1
- package/src/commands/publish.js +137 -12
- package/src/commands/pull.js +9 -4
- package/src/commands/refresh.js +166 -0
- package/src/commands/setup-wizard.js +35 -2
- package/src/commands/status.js +22 -2
- package/src/commands/variation.js +194 -0
- package/src/index.js +187 -9
- package/src/lib/api-client.js +61 -35
- package/src/lib/auto-update/refresh.js +598 -0
- package/src/lib/auto-update/scene-runtime.compose.tsx +73 -0
- package/src/lib/auto-update/spec.js +89 -0
- package/src/lib/capture-engine.js +73 -0
- package/src/lib/capture-script-runner.js +280 -134
- package/src/lib/certification.js +23 -1
- package/src/lib/compose-context.js +156 -0
- package/src/lib/compose-pack.js +42 -0
- package/src/lib/compose-runtime.js +34 -0
- package/src/lib/compose-upload.js +142 -0
- package/src/lib/config.js +2 -2
- package/src/lib/dom-capture.js +64 -0
- package/src/lib/record-clip.js +83 -3
- package/src/lib/record-config.js +0 -4
- package/src/lib/resolve-targets.js +60 -0
- package/src/lib/run-manifest.js +45 -0
- package/src/lib/ui-api-helpers.js +118 -0
- package/src/lib/ui-api.js +28 -820
- package/src/lib/ui-asset-cleanup.js +62 -0
- package/src/lib/ui-output-versions.js +165 -0
- package/src/lib/ui-recorder-routes.js +341 -0
- package/src/lib/ui-scenario-metadata.js +161 -0
- package/vendor/compose/dist/auto-update.cjs +5544 -0
- package/vendor/compose/dist/auto-update.mjs +5518 -0
- package/vendor/compose/dist/capture.cjs +1450 -0
- package/vendor/compose/dist/capture.mjs +1416 -0
- package/vendor/compose/dist/eligibility.cjs +5331 -0
- package/vendor/compose/dist/eligibility.mjs +5313 -0
- package/vendor/compose/dist/index.cjs +2046 -0
- package/vendor/compose/dist/index.mjs +1997 -0
- package/vendor/compose/dist/jsx-dev-runtime.cjs +55 -0
- package/vendor/compose/dist/jsx-dev-runtime.mjs +27 -0
- package/vendor/compose/dist/jsx-runtime.cjs +58 -0
- package/vendor/compose/dist/jsx-runtime.mjs +31 -0
- package/vendor/compose/dist/render.cjs +558 -0
- package/vendor/compose/dist/render.mjs +515 -0
- package/vendor/compose/dist/verify-cli.cjs +3806 -0
- package/vendor/compose/dist/verify-cli.mjs +3812 -0
- package/vendor/compose/dist/verify.cjs +3880 -0
- package/vendor/compose/dist/verify.mjs +3858 -0
- package/web/manager/dist/assets/{index-CvleJUur.js → index-D0S2otug.js} +56 -56
- package/web/manager/dist/index.html +1 -1
- package/src/commands/ingest.js +0 -458
- package/src/commands/setup.js +0 -165
- package/src/lib/playwright-runner.js +0 -252
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
// playwright-runner.js - Generic Playwright runner for executing steps
|
|
2
|
-
const { chromium } = require("playwright");
|
|
3
|
-
const path = require("path");
|
|
4
|
-
const fs = require("fs-extra");
|
|
5
|
-
const { buildLaunchOptions } = require("./ci-detect");
|
|
6
|
-
const { resolveSecretsInObject } = require("./secrets");
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Wait for element with retries and fallbacks
|
|
10
|
-
* @param {Page} page - Playwright page
|
|
11
|
-
* @param {string} selector - CSS selector
|
|
12
|
-
* @param {Object} options - Options
|
|
13
|
-
* @returns {Promise<Locator>}
|
|
14
|
-
*/
|
|
15
|
-
async function waitForElement(page, selector, options = {}) {
|
|
16
|
-
const { timeout = 10000, action = "interact" } = options;
|
|
17
|
-
|
|
18
|
-
// First, wait for the page to be stable (no network activity)
|
|
19
|
-
try {
|
|
20
|
-
await page.waitForLoadState("networkidle", { timeout: 5000 });
|
|
21
|
-
} catch (e) {
|
|
22
|
-
// Continue even if networkidle times out
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Try the selector directly
|
|
26
|
-
const locator = page.locator(selector);
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
await locator.first().waitFor({ state: "visible", timeout });
|
|
30
|
-
return locator.first();
|
|
31
|
-
} catch (e) {
|
|
32
|
-
// If selector fails, try some fallback strategies
|
|
33
|
-
console.log(
|
|
34
|
-
` ⚠ Selector "${selector}" not immediately found, trying fallbacks...`
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
// Strategy 1: Wait a bit longer for dynamic content
|
|
38
|
-
await page.waitForTimeout(1000);
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
await locator.first().waitFor({ state: "visible", timeout: 3000 });
|
|
42
|
-
return locator.first();
|
|
43
|
-
} catch (e2) {
|
|
44
|
-
// Strategy 2: Try scrolling to make element visible
|
|
45
|
-
try {
|
|
46
|
-
await page.evaluate(() =>
|
|
47
|
-
window.scrollTo(0, document.body.scrollHeight / 2)
|
|
48
|
-
);
|
|
49
|
-
await page.waitForTimeout(500);
|
|
50
|
-
await locator.first().waitFor({ state: "visible", timeout: 2000 });
|
|
51
|
-
return locator.first();
|
|
52
|
-
} catch (e3) {
|
|
53
|
-
// Give up with helpful error
|
|
54
|
-
const count = await locator.count();
|
|
55
|
-
if (count === 0) {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`Element not found: "${selector}" - no matching elements on page`
|
|
58
|
-
);
|
|
59
|
-
} else {
|
|
60
|
-
throw new Error(
|
|
61
|
-
`Element "${selector}" exists (${count} matches) but not visible/clickable`
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Run a sequence of steps with Playwright
|
|
71
|
-
* Based on test/persona-injection/generic_runner.js and test/capturing-target/element_runner.js
|
|
72
|
-
*
|
|
73
|
-
* @param {Object} options - Run options
|
|
74
|
-
* @param {string} options.url - URL to navigate to
|
|
75
|
-
* @param {Array} options.steps - Array of step objects
|
|
76
|
-
* @param {string} options.outputDir - Directory to save output files
|
|
77
|
-
* @param {Object} options.context - Context object for variable resolution
|
|
78
|
-
*/
|
|
79
|
-
async function runSteps({ url, steps, outputDir, context }) {
|
|
80
|
-
const browser = await chromium.launch(buildLaunchOptions({ headless: true }));
|
|
81
|
-
const page = await browser.newPage();
|
|
82
|
-
|
|
83
|
-
// Set viewport for consistent rendering
|
|
84
|
-
await page.setViewportSize({ width: 1280, height: 720 });
|
|
85
|
-
|
|
86
|
-
// Set a reasonable default timeout
|
|
87
|
-
page.setDefaultTimeout(20000); // 20 seconds
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
console.log(` Navigating to ${url}`);
|
|
91
|
-
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
92
|
-
|
|
93
|
-
// Wait for initial page load
|
|
94
|
-
await page
|
|
95
|
-
.waitForLoadState("networkidle", { timeout: 10000 })
|
|
96
|
-
.catch(() => {});
|
|
97
|
-
|
|
98
|
-
for (let index = 0; index < steps.length; index++) {
|
|
99
|
-
const step = steps[index];
|
|
100
|
-
console.log(
|
|
101
|
-
` Executing step ${index + 1}/${steps.length}: ${step.action} ${
|
|
102
|
-
step.selector || ""
|
|
103
|
-
}`
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
// Resolve secrets in all step fields
|
|
107
|
-
const resolvedStep = resolveSecretsInObject(step);
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
switch (resolvedStep.action) {
|
|
111
|
-
case "goto":
|
|
112
|
-
await page.goto(resolvedStep.url || url, {
|
|
113
|
-
waitUntil: "domcontentloaded",
|
|
114
|
-
});
|
|
115
|
-
await page
|
|
116
|
-
.waitForLoadState("networkidle", { timeout: 10000 })
|
|
117
|
-
.catch(() => {});
|
|
118
|
-
break;
|
|
119
|
-
|
|
120
|
-
case "type":
|
|
121
|
-
case "input": {
|
|
122
|
-
const inputElement = await waitForElement(
|
|
123
|
-
page,
|
|
124
|
-
resolvedStep.selector,
|
|
125
|
-
{ action: "fill" }
|
|
126
|
-
);
|
|
127
|
-
await inputElement.fill(resolvedStep.text || "");
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
case "click": {
|
|
132
|
-
const clickElement = await waitForElement(
|
|
133
|
-
page,
|
|
134
|
-
resolvedStep.selector,
|
|
135
|
-
{ action: "click" }
|
|
136
|
-
);
|
|
137
|
-
await clickElement.click();
|
|
138
|
-
// Small delay after click to let page react
|
|
139
|
-
await page.waitForTimeout(300);
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
case "hover": {
|
|
144
|
-
const hoverElement = await waitForElement(
|
|
145
|
-
page,
|
|
146
|
-
resolvedStep.selector,
|
|
147
|
-
{ action: "hover" }
|
|
148
|
-
);
|
|
149
|
-
await hoverElement.hover();
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
case "waitForSelector":
|
|
154
|
-
await waitForElement(page, resolvedStep.selector);
|
|
155
|
-
break;
|
|
156
|
-
|
|
157
|
-
case "wait":
|
|
158
|
-
await page.waitForTimeout(
|
|
159
|
-
resolvedStep.ms || resolvedStep.duration || 1000
|
|
160
|
-
);
|
|
161
|
-
break;
|
|
162
|
-
|
|
163
|
-
case "screenshot":
|
|
164
|
-
await handleScreenshot(page, resolvedStep, outputDir, index);
|
|
165
|
-
break;
|
|
166
|
-
|
|
167
|
-
default:
|
|
168
|
-
console.warn(` ⚠ Unknown action: ${resolvedStep.action}`);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
console.log(` ✓ Step ${index + 1} completed`);
|
|
172
|
-
} catch (stepError) {
|
|
173
|
-
// Enhanced error message for selector failures
|
|
174
|
-
const selectorInfo = resolvedStep.selector
|
|
175
|
-
? ` (selector: "${resolvedStep.selector}")`
|
|
176
|
-
: "";
|
|
177
|
-
console.error(
|
|
178
|
-
` ❌ Step ${index + 1} failed: ${step.action}${selectorInfo}`
|
|
179
|
-
);
|
|
180
|
-
console.error(` Error: ${stepError.message}`);
|
|
181
|
-
|
|
182
|
-
// Take a screenshot for debugging
|
|
183
|
-
try {
|
|
184
|
-
const debugPath = path.join(
|
|
185
|
-
outputDir || ".",
|
|
186
|
-
`debug-step-${index + 1}-failure.png`
|
|
187
|
-
);
|
|
188
|
-
await page.screenshot({ path: debugPath, fullPage: true });
|
|
189
|
-
console.error(` Debug screenshot saved: ${debugPath}`);
|
|
190
|
-
} catch (ssError) {
|
|
191
|
-
// Ignore screenshot errors
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Re-throw to stop execution
|
|
195
|
-
throw new Error(
|
|
196
|
-
`Step ${index + 1} (${step.action}) failed: ${stepError.message}`
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
console.log(` ✔ All ${steps.length} steps completed successfully`);
|
|
202
|
-
} finally {
|
|
203
|
-
await browser.close();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Handle screenshot step
|
|
209
|
-
* Based on test/capturing-target/element_runner.js
|
|
210
|
-
*/
|
|
211
|
-
function resolveScreenshotPath(step, index) {
|
|
212
|
-
if (step.path) {
|
|
213
|
-
return step.path;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const baseName = step.captureKey || step.key;
|
|
217
|
-
if (baseName) {
|
|
218
|
-
return path.extname(baseName) ? baseName : `${baseName}.png`;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return `step-${(index ?? 0) + 1}.png`;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async function handleScreenshot(page, step, outputDir, index) {
|
|
225
|
-
const relativePath = resolveScreenshotPath(step, index);
|
|
226
|
-
const finalPath = path.join(outputDir, relativePath);
|
|
227
|
-
fs.ensureDirSync(path.dirname(finalPath));
|
|
228
|
-
|
|
229
|
-
if (step.selector) {
|
|
230
|
-
// Capture specific element
|
|
231
|
-
const element = await page.locator(step.selector).first();
|
|
232
|
-
await element.screenshot({ path: finalPath });
|
|
233
|
-
console.log(` ✔ Captured element and saved to ${finalPath}`);
|
|
234
|
-
} else {
|
|
235
|
-
// Capture full page
|
|
236
|
-
const screenshotOptions = {
|
|
237
|
-
path: finalPath,
|
|
238
|
-
fullPage: !step.clip,
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
if (step.clip) {
|
|
242
|
-
screenshotOptions.clip = step.clip;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
await page.screenshot(screenshotOptions);
|
|
246
|
-
console.log(` ✔ Captured full page and saved to ${finalPath}`);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
module.exports = {
|
|
251
|
-
runSteps,
|
|
252
|
-
};
|