@vizzly-testing/cli 0.34.0 → 0.35.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 (37) hide show
  1. package/README.md +67 -7
  2. package/dist/api/core.js +18 -4
  3. package/dist/api/endpoints.js +38 -15
  4. package/dist/api/index.js +1 -1
  5. package/dist/cli.js +270 -194
  6. package/dist/client/index.js +62 -21
  7. package/dist/commands/api.js +9 -3
  8. package/dist/commands/preview.js +30 -26
  9. package/dist/commands/project.js +1 -1
  10. package/dist/commands/run.js +25 -10
  11. package/dist/commands/status.js +14 -1
  12. package/dist/commands/tdd-daemon-process.js +5 -1
  13. package/dist/commands/tdd-daemon.js +217 -139
  14. package/dist/commands/tdd.js +26 -5
  15. package/dist/commands/upload.js +31 -13
  16. package/dist/reporter/reporter-bundle.iife.js +6 -6
  17. package/dist/sdk/index.js +23 -9
  18. package/dist/server/handlers/api-handler.js +3 -2
  19. package/dist/server/handlers/tdd-handler.js +5 -1
  20. package/dist/server/routers/screenshot.js +11 -4
  21. package/dist/services/build-manager.js +6 -1
  22. package/dist/tdd/tdd-service.js +6 -2
  23. package/dist/test-runner/core.js +8 -3
  24. package/dist/test-runner/operations.js +19 -3
  25. package/dist/types/client.d.ts +32 -5
  26. package/dist/types/index.d.ts +33 -5
  27. package/dist/uploader/core.js +41 -9
  28. package/dist/uploader/operations.js +19 -17
  29. package/dist/utils/config-loader.js +13 -6
  30. package/dist/utils/context.js +46 -76
  31. package/dist/utils/environment-config.js +20 -0
  32. package/dist/utils/output.js +8 -5
  33. package/dist/utils/screenshot-options.js +60 -10
  34. package/package.json +1 -1
  35. package/skills/vizzly/SKILL.md +12 -4
  36. package/skills/vizzly/references/cli-context.md +8 -2
  37. package/skills/vizzly/references/setup-ci.md +3 -1
@@ -1,4 +1,5 @@
1
1
  import { createApiClient as defaultCreateApiClient, finalizeBuild as defaultFinalizeBuild, getTokenContext as defaultGetTokenContext } from '../api/index.js';
2
+ import { CONFIG_DEFAULTS } from '../config/core.js';
2
3
  import { createUploader as defaultCreateUploader } from '../uploader/index.js';
3
4
  import { getAppBaseUrl } from '../utils/api-url.js';
4
5
  import { loadConfig as defaultLoadConfig } from '../utils/config-loader.js';
@@ -73,12 +74,12 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
73
74
  });
74
75
  let buildId = null;
75
76
  let config = null;
76
- const uploadStartTime = Date.now();
77
+ let uploadStartTime = Date.now();
77
78
  try {
78
79
  output.info('Starting upload process...');
79
80
 
80
81
  // Load configuration with CLI overrides
81
- const allOptions = {
82
+ let allOptions = {
82
83
  ...globalOptions,
83
84
  ...options
84
85
  };
@@ -95,11 +96,12 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
95
96
  }
96
97
 
97
98
  // Collect git metadata if not provided
98
- const branch = await detectBranch(options.branch);
99
- const commit = await detectCommit(options.commit);
100
- const message = options.message || (await detectCommitMessage());
101
- const buildName = await generateBuildNameWithGit(options.buildName);
102
- const pullRequestNumber = detectPullRequestNumber();
99
+ let configuredBuildName = config.build.name && config.build.name !== CONFIG_DEFAULTS.build.name ? config.build.name : undefined;
100
+ let branch = await detectBranch(options.branch || config.build.branch);
101
+ let commit = await detectCommit(options.commit || config.build.commit);
102
+ let message = options.message || config.build.message || (await detectCommitMessage());
103
+ let buildName = await generateBuildNameWithGit(options.buildName || configuredBuildName);
104
+ let pullRequestNumber = detectPullRequestNumber();
103
105
  output.info(`Uploading screenshots from: ${screenshotsPath}`);
104
106
  if (globalOptions.verbose) {
105
107
  output.info('Configuration loaded');
@@ -119,7 +121,7 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
119
121
  });
120
122
 
121
123
  // Prepare upload options with progress callback
122
- const uploadOptions = {
124
+ let uploadOptions = {
123
125
  screenshotsDir: screenshotsPath,
124
126
  buildName,
125
127
  branch,
@@ -127,12 +129,13 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
127
129
  message,
128
130
  environment: config.build.environment,
129
131
  threshold: config.comparison.threshold,
132
+ minClusterSize: config.comparison.minClusterSize,
130
133
  uploadAll: options.uploadAll || false,
131
134
  metadata: options.metadata ? JSON.parse(options.metadata) : {},
132
135
  pullRequestNumber,
133
136
  parallelId: config.parallelId,
134
137
  onProgress: progressData => {
135
- const {
138
+ let {
136
139
  message: progressMessage,
137
140
  current,
138
141
  total,
@@ -158,7 +161,7 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
158
161
 
159
162
  // Start upload
160
163
  output.progress('Starting upload...');
161
- const result = await uploader.upload(uploadOptions);
164
+ let result = await uploader.upload(uploadOptions);
162
165
  buildId = result.buildId; // Ensure we have the buildId
163
166
 
164
167
  // Write session for subsequent commands (like preview)
@@ -263,8 +266,10 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
263
266
  executionTimeMs
264
267
  });
265
268
  output.cleanup();
269
+ let success = buildResult.failedComparisons === 0;
266
270
  return {
267
- success: buildResult.failedComparisons === 0,
271
+ success,
272
+ exitCode: success ? 0 : 1,
268
273
  result
269
274
  };
270
275
  }
@@ -283,6 +288,14 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
283
288
  let waitBuildUrl = buildResult.url || (await buildUrlConstructor(result.buildId, config.apiUrl, config.apiKey, deps));
284
289
  output.blank();
285
290
  output.labelValue('View', output.link('Results', waitBuildUrl));
291
+ if (buildResult.failedComparisons > 0) {
292
+ output.cleanup();
293
+ return {
294
+ success: false,
295
+ exitCode: 1,
296
+ result
297
+ };
298
+ }
286
299
  }
287
300
  output.cleanup();
288
301
  return {
@@ -300,11 +313,10 @@ export async function uploadCommand(screenshotsPath, options = {}, globalOptions
300
313
  message: 'Vizzly API unavailable - upload skipped',
301
314
  executionTimeMs: Date.now() - uploadStartTime
302
315
  });
303
- output.cleanup();
304
316
  } else {
305
317
  output.warn('Vizzly API unavailable - upload skipped. Your tests still ran.');
306
- output.cleanup();
307
318
  }
319
+ output.cleanup();
308
320
  return {
309
321
  success: true,
310
322
  result: {
@@ -381,6 +393,12 @@ export function validateUploadOptions(screenshotsPath, options) {
381
393
  errors.push('Threshold must be a non-negative number (CIEDE2000 Delta E)');
382
394
  }
383
395
  }
396
+ if (options.minClusterSize !== undefined) {
397
+ let minClusterSize = Number(options.minClusterSize);
398
+ if (!Number.isInteger(minClusterSize) || minClusterSize < 1) {
399
+ errors.push('Min cluster size must be a positive integer');
400
+ }
401
+ }
384
402
  if (options.batchSize !== undefined) {
385
403
  let n = Number(options.batchSize);
386
404
  if (!Number.isInteger(n) || n <= 0) {