@vizzly-testing/cli 0.21.2 → 0.22.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/dist/cli.js +43 -13
- package/dist/commands/tdd-daemon.js +3 -2
- package/dist/reporter/reporter-bundle.css +1 -1
- package/dist/reporter/reporter-bundle.iife.js +28 -28
- package/dist/reporter-ssr/ssr-entry.js +558 -0
- package/dist/server/handlers/tdd-handler.js +22 -26
- package/dist/services/static-report-generator.js +205 -0
- package/dist/utils/browser.js +24 -4
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,8 @@ import { validateWhoamiOptions, whoamiCommand } from './commands/whoami.js';
|
|
|
16
16
|
import { createPluginServices } from './plugin-api.js';
|
|
17
17
|
import { loadPlugins } from './plugin-loader.js';
|
|
18
18
|
import { createServices } from './services/index.js';
|
|
19
|
+
import { generateStaticReport, getReportFileUrl } from './services/static-report-generator.js';
|
|
20
|
+
import { openBrowser } from './utils/browser.js';
|
|
19
21
|
import { colors } from './utils/colors.js';
|
|
20
22
|
import { loadConfig } from './utils/config-loader.js';
|
|
21
23
|
import { getContext } from './utils/context.js';
|
|
@@ -274,7 +276,7 @@ program.command('upload').description('Upload screenshots to Vizzly').argument('
|
|
|
274
276
|
const tddCmd = program.command('tdd').description('Run tests in TDD mode with local visual comparisons');
|
|
275
277
|
|
|
276
278
|
// TDD Start - Background server
|
|
277
|
-
tddCmd.command('start').description('Start background TDD server with dashboard').option('--port <port>', 'Port for TDD server', '47392').option('--open', 'Open dashboard in browser').option('--baseline-build <id>', 'Use specific build as baseline').option('--baseline-comparison <id>', 'Use specific comparison as baseline').option('--environment <env>', 'Environment name', 'test').option('--threshold <number>', 'Comparison threshold', parseFloat).option('--timeout <ms>', 'Server timeout in milliseconds', '30000').option('--token <token>', 'API token override').option('--daemon-child', 'Internal: run as daemon child process').action(async options => {
|
|
279
|
+
tddCmd.command('start').description('Start background TDD server with dashboard').option('--port <port>', 'Port for TDD server', '47392').option('--open', 'Open dashboard in browser').option('--baseline-build <id>', 'Use specific build as baseline').option('--baseline-comparison <id>', 'Use specific comparison as baseline').option('--environment <env>', 'Environment name', 'test').option('--threshold <number>', 'Comparison threshold', parseFloat).option('--timeout <ms>', 'Server timeout in milliseconds', '30000').option('--fail-on-diff', 'Fail tests when visual differences are detected').option('--token <token>', 'API token override').option('--daemon-child', 'Internal: run as daemon child process').action(async options => {
|
|
278
280
|
const globalOptions = program.opts();
|
|
279
281
|
|
|
280
282
|
// If this is a daemon child process, run the server directly
|
|
@@ -298,7 +300,7 @@ tddCmd.command('status').description('Check TDD server status').action(async opt
|
|
|
298
300
|
});
|
|
299
301
|
|
|
300
302
|
// TDD Run - One-off test run with ephemeral server (generates static report)
|
|
301
|
-
tddCmd.command('run <command>').description('Run tests once in TDD mode with local visual comparisons').option('--port <port>', 'Port for TDD server', '47392').option('--branch <branch>', 'Git branch override').option('--environment <env>', 'Environment name', 'test').option('--threshold <number>', 'Comparison threshold', parseFloat).option('--token <token>', 'API token override').option('--timeout <ms>', 'Server timeout in milliseconds', '30000').option('--baseline-build <id>', 'Use specific build as baseline').option('--baseline-comparison <id>', 'Use specific comparison as baseline').option('--set-baseline', 'Accept current screenshots as new baseline (overwrites existing)').action(async (command, options) => {
|
|
303
|
+
tddCmd.command('run <command>').description('Run tests once in TDD mode with local visual comparisons').option('--port <port>', 'Port for TDD server', '47392').option('--branch <branch>', 'Git branch override').option('--environment <env>', 'Environment name', 'test').option('--threshold <number>', 'Comparison threshold', parseFloat).option('--token <token>', 'API token override').option('--timeout <ms>', 'Server timeout in milliseconds', '30000').option('--baseline-build <id>', 'Use specific build as baseline').option('--baseline-comparison <id>', 'Use specific comparison as baseline').option('--set-baseline', 'Accept current screenshots as new baseline (overwrites existing)').option('--fail-on-diff', 'Fail tests when visual differences are detected').option('--no-open', 'Skip opening report in browser').action(async (command, options) => {
|
|
302
304
|
const globalOptions = program.opts();
|
|
303
305
|
|
|
304
306
|
// Validate options
|
|
@@ -315,21 +317,49 @@ tddCmd.command('run <command>').description('Run tests once in TDD mode with loc
|
|
|
315
317
|
cleanup
|
|
316
318
|
} = await tddCommand(command, options, globalOptions);
|
|
317
319
|
|
|
318
|
-
//
|
|
320
|
+
// Track cleanup state to prevent double cleanup
|
|
321
|
+
let isCleaningUp = false;
|
|
319
322
|
const handleCleanup = async () => {
|
|
323
|
+
if (isCleaningUp) return;
|
|
324
|
+
isCleaningUp = true;
|
|
320
325
|
await cleanup();
|
|
321
326
|
};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
|
|
328
|
+
// Set up cleanup on process signals
|
|
329
|
+
const sigintHandler = () => {
|
|
330
|
+
handleCleanup().then(() => process.exit(result?.exitCode || 0));
|
|
331
|
+
};
|
|
332
|
+
const sigtermHandler = () => {
|
|
333
|
+
handleCleanup().then(() => process.exit(result?.exitCode || 0));
|
|
334
|
+
};
|
|
335
|
+
process.once('SIGINT', sigintHandler);
|
|
336
|
+
process.once('SIGTERM', sigtermHandler);
|
|
337
|
+
|
|
338
|
+
// If there are comparisons, generate static report
|
|
339
|
+
const hasComparisons = result?.comparisons?.length > 0;
|
|
340
|
+
if (hasComparisons) {
|
|
341
|
+
// Note: Tests have completed at this point, so report-data.json is stable.
|
|
342
|
+
// The report reflects the final state of all comparisons.
|
|
343
|
+
const reportResult = await generateStaticReport(process.cwd());
|
|
344
|
+
if (reportResult.success) {
|
|
345
|
+
const reportUrl = getReportFileUrl(reportResult.reportPath);
|
|
346
|
+
output.print(` ${colors.brand.textTertiary('→')} Report: ${colors.blue(reportUrl)}`);
|
|
347
|
+
output.blank();
|
|
348
|
+
|
|
349
|
+
// Open report in browser unless --no-open
|
|
350
|
+
if (options.open !== false) {
|
|
351
|
+
await openBrowser(reportUrl);
|
|
352
|
+
}
|
|
353
|
+
} else {
|
|
354
|
+
output.warn(`Failed to generate static report: ${reportResult.error}`);
|
|
355
|
+
}
|
|
331
356
|
}
|
|
332
|
-
|
|
357
|
+
|
|
358
|
+
// Remove signal handlers before normal cleanup to prevent double cleanup
|
|
359
|
+
process.off('SIGINT', sigintHandler);
|
|
360
|
+
process.off('SIGTERM', sigtermHandler);
|
|
361
|
+
await handleCleanup();
|
|
362
|
+
process.exit(result?.exitCode || 0);
|
|
333
363
|
});
|
|
334
364
|
program.command('run').description('Run tests with Vizzly integration').argument('<command>', 'Test command to run').option('--port <port>', 'Port for screenshot server', '47392').option('-b, --build-name <name>', 'Custom build name').option('--branch <branch>', 'Git branch override').option('--commit <sha>', 'Git commit SHA').option('--message <msg>', 'Commit message').option('--environment <env>', 'Environment name', 'test').option('--token <token>', 'API token override').option('--wait', 'Wait for build completion').option('--timeout <ms>', 'Server timeout in milliseconds', '30000').option('--allow-no-token', 'Allow running without API token').option('--upload-all', 'Upload all screenshots without SHA deduplication').option('--parallel-id <id>', 'Unique identifier for parallel test execution').action(async (command, options) => {
|
|
335
365
|
const globalOptions = program.opts();
|
|
@@ -56,7 +56,7 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
56
56
|
// CLI entry point
|
|
57
57
|
'tdd', 'start', '--daemon-child',
|
|
58
58
|
// Special flag for child process
|
|
59
|
-
'--port', port.toString(), ...(options.open ? ['--open'] : []), ...(options.baselineBuild ? ['--baseline-build', options.baselineBuild] : []), ...(options.baselineComparison ? ['--baseline-comparison', options.baselineComparison] : []), ...(options.environment ? ['--environment', options.environment] : []), ...(options.threshold !== undefined ? ['--threshold', options.threshold.toString()] : []), ...(options.timeout ? ['--timeout', options.timeout] : []), ...(options.token ? ['--token', options.token] : []), ...(globalOptions.json ? ['--json'] : []), ...(globalOptions.verbose ? ['--verbose'] : []), ...(globalOptions.noColor ? ['--no-color'] : [])], {
|
|
59
|
+
'--port', port.toString(), ...(options.open ? ['--open'] : []), ...(options.baselineBuild ? ['--baseline-build', options.baselineBuild] : []), ...(options.baselineComparison ? ['--baseline-comparison', options.baselineComparison] : []), ...(options.environment ? ['--environment', options.environment] : []), ...(options.threshold !== undefined ? ['--threshold', options.threshold.toString()] : []), ...(options.timeout ? ['--timeout', options.timeout] : []), ...(options.failOnDiff ? ['--fail-on-diff'] : []), ...(options.token ? ['--token', options.token] : []), ...(globalOptions.json ? ['--json'] : []), ...(globalOptions.verbose ? ['--verbose'] : []), ...(globalOptions.noColor ? ['--no-color'] : [])], {
|
|
60
60
|
detached: true,
|
|
61
61
|
stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
|
|
62
62
|
cwd: process.cwd()
|
|
@@ -199,7 +199,8 @@ export async function runDaemonChild(options = {}, globalOptions = {}) {
|
|
|
199
199
|
const serverInfo = {
|
|
200
200
|
pid: process.pid,
|
|
201
201
|
port: port,
|
|
202
|
-
startTime: Date.now()
|
|
202
|
+
startTime: Date.now(),
|
|
203
|
+
failOnDiff: options.failOnDiff || false
|
|
203
204
|
};
|
|
204
205
|
writeFileSync(join(vizzlyDir, 'server.json'), JSON.stringify(serverInfo, null, 2));
|
|
205
206
|
|