@reshotdev/screenshot 0.0.1-beta.2 โ 0.0.1-beta.20
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/LICENSE +1 -1
- package/README.md +138 -47
- package/package.json +27 -16
- package/src/commands/auth.js +159 -30
- package/src/commands/capture-dom.js +50 -0
- package/src/commands/certify.js +62 -0
- package/src/commands/compose.js +220 -0
- package/src/commands/doctor-release.js +74 -0
- package/src/commands/doctor-target.js +108 -0
- package/src/commands/drifts.js +16 -69
- package/src/commands/import-tests.js +13 -13
- package/src/commands/init.js +16 -277
- package/src/commands/publish.js +484 -257
- package/src/commands/pull.js +302 -35
- package/src/commands/refresh.js +166 -0
- package/src/commands/run.js +292 -12
- package/src/commands/setup-wizard.js +348 -496
- package/src/commands/status.js +334 -126
- package/src/commands/sync.js +28 -236
- package/src/commands/ui.js +1 -1
- package/src/commands/variation.js +194 -0
- package/src/commands/verify-publish.js +46 -0
- package/src/index.js +383 -118
- package/src/lib/api-client.js +172 -60
- 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 +179 -9
- package/src/lib/capture-script-runner.js +639 -214
- package/src/lib/certification.js +887 -0
- 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 +186 -81
- package/src/lib/dom-capture.js +64 -0
- package/src/lib/ensure-browser.js +147 -0
- package/src/lib/output-path-template.js +3 -3
- package/src/lib/record-cdp.js +288 -16
- package/src/lib/record-clip.js +83 -3
- package/src/lib/record-config.js +1 -5
- package/src/lib/release-doctor.js +321 -0
- package/src/lib/resolve-targets.js +60 -0
- package/src/lib/run-manifest.js +148 -0
- package/src/lib/standalone-mode.js +1 -1
- package/src/lib/storage-providers.js +5 -5
- package/src/lib/style-engine.js +5 -5
- package/src/lib/target-contract.js +292 -0
- package/src/lib/ui-api-helpers.js +118 -0
- package/src/lib/ui-api.js +31 -824
- 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-D0S2otug.js +507 -0
- package/web/manager/dist/index.html +1 -1
- package/src/commands/ci-run.js +0 -123
- package/src/commands/ci-setup.js +0 -288
- package/src/commands/ingest.js +0 -458
- package/src/commands/setup.js +0 -137
- package/src/commands/validate-docs.js +0 -529
- package/src/lib/playwright-runner.js +0 -252
- package/web/manager/dist/assets/index--ZgioErz.js +0 -507
package/src/commands/run.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
// run.js - Execute all scenarios from config using the robust capture engine
|
|
2
|
+
const axios = require("axios");
|
|
2
3
|
const chalk = require("chalk");
|
|
3
4
|
const fs = require("fs-extra");
|
|
4
5
|
const path = require("path");
|
|
5
6
|
const config = require("../lib/config");
|
|
6
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
runAllScenarios,
|
|
9
|
+
generateVersionTimestamp,
|
|
10
|
+
detectOptimalConcurrency,
|
|
11
|
+
resolveAuthPreflightTargets,
|
|
12
|
+
} = require("../lib/capture-script-runner");
|
|
7
13
|
const { getBaselines } = require("../lib/api-client");
|
|
8
14
|
const {
|
|
9
15
|
downloadBaselines,
|
|
@@ -14,6 +20,12 @@ const {
|
|
|
14
20
|
writeLocalDiffManifest,
|
|
15
21
|
CACHE_DIR,
|
|
16
22
|
} = require("../lib/diff-engine");
|
|
23
|
+
const {
|
|
24
|
+
checkCdpEndpoint,
|
|
25
|
+
getDefaultSessionPath,
|
|
26
|
+
assessSessionHealth,
|
|
27
|
+
} = require("../lib/record-cdp");
|
|
28
|
+
const { writeRunManifest, normalizeScenarioResults } = require("../lib/run-manifest");
|
|
17
29
|
|
|
18
30
|
/**
|
|
19
31
|
* Generate all variant combinations from dimensions config
|
|
@@ -68,6 +80,224 @@ function generateVariantCombinations(dimensions, dimensionKeys = null) {
|
|
|
68
80
|
});
|
|
69
81
|
}
|
|
70
82
|
|
|
83
|
+
async function probeBaseUrl(baseUrl) {
|
|
84
|
+
if (!baseUrl) {
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
status: null,
|
|
88
|
+
message: "baseUrl is not configured.",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const response = await axios.get(baseUrl, {
|
|
94
|
+
timeout: 8000,
|
|
95
|
+
maxRedirects: 0,
|
|
96
|
+
validateStatus: () => true,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (response.status >= 500) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
status: response.status,
|
|
103
|
+
message: `baseUrl responded with ${response.status}. Fix the app before running capture.`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
ok: true,
|
|
109
|
+
status: response.status,
|
|
110
|
+
message: `baseUrl responded with ${response.status}`,
|
|
111
|
+
};
|
|
112
|
+
} catch (error) {
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
status: null,
|
|
116
|
+
message:
|
|
117
|
+
`Could not reach baseUrl ${baseUrl}. ` +
|
|
118
|
+
`Make sure the app is running and reachable before capture. (${error.message})`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function formatSessionAge(minutes) {
|
|
124
|
+
if (minutes < 60) {
|
|
125
|
+
return `${minutes}m`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const hours = Math.round(minutes / 60);
|
|
129
|
+
if (hours < 24) {
|
|
130
|
+
return `${hours}h`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return `${Math.round(hours / 24)}d`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function writeRunPreflightReport(report) {
|
|
137
|
+
const diagnosticsPath = path.join(
|
|
138
|
+
process.cwd(),
|
|
139
|
+
".reshot",
|
|
140
|
+
"diagnostics",
|
|
141
|
+
"run-preflight.json",
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
fs.ensureDirSync(path.dirname(diagnosticsPath));
|
|
146
|
+
fs.writeJsonSync(diagnosticsPath, report, { spaces: 2 });
|
|
147
|
+
} catch (error) {
|
|
148
|
+
report.diagnosticsWriteError = error.message;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return diagnosticsPath;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function buildRunPreflightReport(docSyncConfig, options = {}) {
|
|
155
|
+
const { scenarioKeys = null } = options;
|
|
156
|
+
const validation = config.validateConfig({
|
|
157
|
+
scenarioKeys,
|
|
158
|
+
requireReadyContract: docSyncConfig.target?.tier === "certified",
|
|
159
|
+
});
|
|
160
|
+
const errors = [...validation.errors];
|
|
161
|
+
const warnings = [...validation.warnings];
|
|
162
|
+
const report = {
|
|
163
|
+
generatedAt: new Date().toISOString(),
|
|
164
|
+
ok: false,
|
|
165
|
+
baseUrl: docSyncConfig.baseUrl || null,
|
|
166
|
+
selectedScenarioKeys: validation.details?.selectedScenarioKeys || [],
|
|
167
|
+
configValidation: validation,
|
|
168
|
+
checks: [],
|
|
169
|
+
auth: {
|
|
170
|
+
required: Boolean(validation.details?.liveAuthScenarioCount),
|
|
171
|
+
sessionPath: null,
|
|
172
|
+
hasCachedSession: false,
|
|
173
|
+
sessionAgeMinutes: null,
|
|
174
|
+
sessionCompatible: null,
|
|
175
|
+
sessionSourceOrigin: null,
|
|
176
|
+
sessionStale: null,
|
|
177
|
+
preflightTargets: [],
|
|
178
|
+
cdpAvailable: null,
|
|
179
|
+
},
|
|
180
|
+
errors,
|
|
181
|
+
warnings,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
if (validation.details?.baseUrl) {
|
|
185
|
+
const baseUrlCheck = await probeBaseUrl(validation.details.baseUrl);
|
|
186
|
+
report.checks.push({ name: "baseUrl", ...baseUrlCheck });
|
|
187
|
+
if (!baseUrlCheck.ok) {
|
|
188
|
+
errors.push(baseUrlCheck.message);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (report.auth.required) {
|
|
193
|
+
report.auth.preflightTargets = resolveAuthPreflightTargets(docSyncConfig, {
|
|
194
|
+
scenarioKeys,
|
|
195
|
+
}).targets;
|
|
196
|
+
const sessionPath = getDefaultSessionPath();
|
|
197
|
+
report.auth.sessionPath = sessionPath;
|
|
198
|
+
report.auth.hasCachedSession = fs.existsSync(sessionPath);
|
|
199
|
+
|
|
200
|
+
if (report.auth.hasCachedSession) {
|
|
201
|
+
const sessionHealth = assessSessionHealth(
|
|
202
|
+
sessionPath,
|
|
203
|
+
validation.details?.baseUrl || docSyncConfig.baseUrl || null,
|
|
204
|
+
);
|
|
205
|
+
report.auth.sessionAgeMinutes = sessionHealth.ageMinutes;
|
|
206
|
+
report.auth.sessionCompatible = sessionHealth.compatible;
|
|
207
|
+
report.auth.sessionSourceOrigin = sessionHealth.evidence.sourceOrigin;
|
|
208
|
+
report.auth.sessionStale = sessionHealth.stale;
|
|
209
|
+
report.checks.push({
|
|
210
|
+
name: "authSession",
|
|
211
|
+
ok: sessionHealth.compatible,
|
|
212
|
+
status: sessionHealth.stale ? "stale" : "ready",
|
|
213
|
+
message: sessionHealth.compatible
|
|
214
|
+
? sessionHealth.evidence.sourceOrigin
|
|
215
|
+
? `Cached auth session matches ${sessionHealth.evidence.sourceOrigin}`
|
|
216
|
+
: "Cached auth session is present"
|
|
217
|
+
: sessionHealth.issues[0],
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
warnings.push(...sessionHealth.warnings);
|
|
221
|
+
|
|
222
|
+
if (!sessionHealth.compatible) {
|
|
223
|
+
const cdpCheck = await checkCdpEndpoint();
|
|
224
|
+
report.auth.cdpAvailable = cdpCheck.available;
|
|
225
|
+
report.checks.push({
|
|
226
|
+
name: "cdp",
|
|
227
|
+
ok: cdpCheck.available,
|
|
228
|
+
status: null,
|
|
229
|
+
message: cdpCheck.available
|
|
230
|
+
? "Chrome CDP endpoint is available and can refresh the cached session."
|
|
231
|
+
: `Chrome CDP endpoint is unavailable: ${cdpCheck.error}`,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
if (cdpCheck.available) {
|
|
235
|
+
warnings.push(
|
|
236
|
+
`Cached auth session does not match ${validation.details?.baseUrl || docSyncConfig.baseUrl}. Chrome CDP is available, so Reshot will try to refresh it from the live browser before capture.`,
|
|
237
|
+
);
|
|
238
|
+
} else {
|
|
239
|
+
errors.push(sessionHealth.issues[0]);
|
|
240
|
+
errors.push(
|
|
241
|
+
"Chrome CDP is unavailable, so Reshot cannot automatically replace the mismatched auth session.",
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (sessionHealth.stale) {
|
|
247
|
+
warnings.push(
|
|
248
|
+
`Cached auth session is ${formatSessionAge(sessionHealth.ageMinutes)} old. ` +
|
|
249
|
+
`Refresh it with 'reshot record --refresh-session' if captures start redirecting to login.`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
const cdpCheck = await checkCdpEndpoint();
|
|
254
|
+
report.auth.cdpAvailable = cdpCheck.available;
|
|
255
|
+
report.checks.push({
|
|
256
|
+
name: "cdp",
|
|
257
|
+
ok: cdpCheck.available,
|
|
258
|
+
status: null,
|
|
259
|
+
message: cdpCheck.available
|
|
260
|
+
? "Chrome CDP endpoint is available for live session sync."
|
|
261
|
+
: `Chrome CDP endpoint is unavailable: ${cdpCheck.error}`,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
if (!cdpCheck.available) {
|
|
265
|
+
errors.push(
|
|
266
|
+
"Authenticated scenarios need either a cached .reshot session or a Chrome browser running with remote debugging enabled.",
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
report.ok = errors.length === 0;
|
|
273
|
+
report.diagnosticsPath = writeRunPreflightReport(report);
|
|
274
|
+
return report;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function printRunPreflightReport(report) {
|
|
278
|
+
console.log(chalk.cyan("๐งช Run Preflight\n"));
|
|
279
|
+
|
|
280
|
+
for (const check of report.checks) {
|
|
281
|
+
const prefix = check.ok ? chalk.green(" โ") : chalk.red(" โ");
|
|
282
|
+
const statusSuffix = check.status ? ` (${check.status})` : "";
|
|
283
|
+
console.log(`${prefix} ${check.name}${statusSuffix}: ${check.message}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (const warning of report.warnings) {
|
|
287
|
+
console.log(chalk.yellow(` โ ${warning}`));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
for (const error of report.errors) {
|
|
291
|
+
console.log(chalk.red(` โ ${error}`));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (report.diagnosticsPath) {
|
|
295
|
+
console.log(chalk.gray(`\n Diagnostics: ${report.diagnosticsPath}`));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
console.log();
|
|
299
|
+
}
|
|
300
|
+
|
|
71
301
|
/**
|
|
72
302
|
* Run scenarios from config
|
|
73
303
|
* @param {Object} options - Run options
|
|
@@ -111,6 +341,30 @@ async function runCommand(options = {}) {
|
|
|
111
341
|
return;
|
|
112
342
|
}
|
|
113
343
|
|
|
344
|
+
const preflightReport = await buildRunPreflightReport(docSyncConfig, {
|
|
345
|
+
scenarioKeys,
|
|
346
|
+
});
|
|
347
|
+
printRunPreflightReport(preflightReport);
|
|
348
|
+
|
|
349
|
+
if (!preflightReport.ok) {
|
|
350
|
+
writeRunManifest({
|
|
351
|
+
success: false,
|
|
352
|
+
selectedScenarioKeys: preflightReport.selectedScenarioKeys || scenarioKeys || [],
|
|
353
|
+
outputBaseDir: path.join(
|
|
354
|
+
process.cwd(),
|
|
355
|
+
docSyncConfig.assetDir || ".reshot/output",
|
|
356
|
+
),
|
|
357
|
+
scenarios: [],
|
|
358
|
+
preflight: preflightReport,
|
|
359
|
+
diffEnabled: false,
|
|
360
|
+
});
|
|
361
|
+
process.exitCode = 1;
|
|
362
|
+
if (!noExit) {
|
|
363
|
+
setImmediate(() => process.exit(process.exitCode || 1));
|
|
364
|
+
}
|
|
365
|
+
return { success: false, results: [], preflight: preflightReport };
|
|
366
|
+
}
|
|
367
|
+
|
|
114
368
|
// Determine if diffing is enabled
|
|
115
369
|
// CLI flag takes precedence, then config, default is TRUE (always diff locally)
|
|
116
370
|
const shouldDiff =
|
|
@@ -164,6 +418,23 @@ async function runCommand(options = {}) {
|
|
|
164
418
|
// - If --all-variants or variants are configured: expand all combinations
|
|
165
419
|
const shouldExpandVariants = !noVariants && !variantOverride && hasVariants;
|
|
166
420
|
|
|
421
|
+
const outputBaseDir = path.join(
|
|
422
|
+
process.cwd(),
|
|
423
|
+
docSyncConfig.assetDir || ".reshot/output"
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
function persistRunManifest(success, scenarios) {
|
|
427
|
+
return writeRunManifest({
|
|
428
|
+
success,
|
|
429
|
+
selectedScenarioKeys:
|
|
430
|
+
preflightReport.selectedScenarioKeys || scenarioKeys || [],
|
|
431
|
+
outputBaseDir,
|
|
432
|
+
scenarios: normalizeScenarioResults(scenarios),
|
|
433
|
+
preflight: preflightReport,
|
|
434
|
+
diffEnabled: shouldDiff,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
167
438
|
if (shouldExpandVariants) {
|
|
168
439
|
const combinations = generateVariantCombinations(dimensions);
|
|
169
440
|
|
|
@@ -238,15 +509,17 @@ async function runCommand(options = {}) {
|
|
|
238
509
|
process.exitCode = 1;
|
|
239
510
|
}
|
|
240
511
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
512
|
+
const flattenedScenarioResults = allResults.flatMap(
|
|
513
|
+
(runResult) => runResult.results || [],
|
|
514
|
+
);
|
|
515
|
+
const persisted = persistRunManifest(allSuccess, flattenedScenarioResults);
|
|
516
|
+
console.log(chalk.gray(`\nRun manifest saved to: ${persisted.manifestPath}`));
|
|
244
517
|
|
|
245
518
|
// Exit after variant expansion completes unless called programmatically
|
|
246
519
|
if (!noExit) {
|
|
247
520
|
process.exit(allSuccess ? 0 : 1);
|
|
248
521
|
}
|
|
249
|
-
return { success: allSuccess, results: allResults };
|
|
522
|
+
return { success: allSuccess, results: allResults, runManifest: persisted.manifest };
|
|
250
523
|
}
|
|
251
524
|
}
|
|
252
525
|
|
|
@@ -263,11 +536,6 @@ async function runCommand(options = {}) {
|
|
|
263
536
|
// ============================================
|
|
264
537
|
// POST-PROCESSING: Local Version-to-Version Diffing
|
|
265
538
|
// ============================================
|
|
266
|
-
const outputBaseDir = path.join(
|
|
267
|
-
process.cwd(),
|
|
268
|
-
docSyncConfig.assetDir || ".reshot/output"
|
|
269
|
-
);
|
|
270
|
-
|
|
271
539
|
// ============================================
|
|
272
540
|
// CLOUD BASELINE SYNC: Download approved baselines from platform
|
|
273
541
|
// ============================================
|
|
@@ -464,6 +732,8 @@ async function runCommand(options = {}) {
|
|
|
464
732
|
}
|
|
465
733
|
|
|
466
734
|
console.log(chalk.gray(`\nOutput saved to: ${outputBaseDir}`));
|
|
735
|
+
const persisted = persistRunManifest(result.success, result.results || []);
|
|
736
|
+
console.log(chalk.gray(`Run manifest saved to: ${persisted.manifestPath}`));
|
|
467
737
|
|
|
468
738
|
// Offer to open Studio for review (interactive TTY only, on success)
|
|
469
739
|
if (result.success && process.stdin.isTTY && !noExit) {
|
|
@@ -481,7 +751,11 @@ async function runCommand(options = {}) {
|
|
|
481
751
|
console.log(chalk.cyan("\n๐ฌ Launching Reshot Studio...\n"));
|
|
482
752
|
const uiCommand = require("./ui");
|
|
483
753
|
await uiCommand({ open: true });
|
|
484
|
-
return {
|
|
754
|
+
return {
|
|
755
|
+
success: result.success,
|
|
756
|
+
results: result.results,
|
|
757
|
+
runManifest: persisted.manifest,
|
|
758
|
+
};
|
|
485
759
|
}
|
|
486
760
|
}
|
|
487
761
|
|
|
@@ -490,7 +764,13 @@ async function runCommand(options = {}) {
|
|
|
490
764
|
setImmediate(() => process.exit(process.exitCode || 0));
|
|
491
765
|
}
|
|
492
766
|
|
|
493
|
-
return {
|
|
767
|
+
return {
|
|
768
|
+
success: result.success,
|
|
769
|
+
results: result.results,
|
|
770
|
+
runManifest: persisted.manifest,
|
|
771
|
+
};
|
|
494
772
|
}
|
|
495
773
|
|
|
496
774
|
module.exports = runCommand;
|
|
775
|
+
module.exports.buildRunPreflightReport = buildRunPreflightReport;
|
|
776
|
+
module.exports.probeBaseUrl = probeBaseUrl;
|