@vizzly-testing/cli 0.24.0 → 0.24.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.
@@ -191,6 +191,7 @@ function createSimpleClient(serverUrl) {
191
191
  let isFilePath = typeof imageBuffer === 'string';
192
192
  let image = isFilePath ? imageBuffer : imageBuffer.toString('base64');
193
193
  let type = isFilePath ? 'file-path' : 'base64';
194
+ let httpStart = Date.now();
194
195
  const {
195
196
  status,
196
197
  json
@@ -202,6 +203,10 @@ function createSimpleClient(serverUrl) {
202
203
  properties: options,
203
204
  fullPage: options.fullPage || false
204
205
  }, DEFAULT_TIMEOUT_MS);
206
+ let httpMs = Date.now() - httpStart;
207
+ if (shouldLogClient('debug')) {
208
+ console.debug(`[vizzly-client] ${name} HTTP completed in ${httpMs}ms`);
209
+ }
205
210
  if (status < 200 || status >= 300) {
206
211
  // In TDD mode, if we get 422 (visual difference), don't throw
207
212
  // This allows all screenshots in the test to be captured and compared
@@ -68,8 +68,10 @@ async function discoverInstalledPlugins() {
68
68
  const packageJson = JSON.parse(readFileSync(pkgPath, 'utf-8'));
69
69
 
70
70
  // Check if package has a plugin field
71
- if (packageJson.vizzly?.plugin) {
72
- const pluginRelativePath = packageJson.vizzly.plugin;
71
+ // Support both new `vizzlyPlugin` and legacy `vizzly.plugin` for backwards compatibility
72
+ const pluginField = packageJson.vizzlyPlugin || packageJson.vizzly?.plugin;
73
+ if (pluginField) {
74
+ const pluginRelativePath = pluginField;
73
75
 
74
76
  // Security: Ensure plugin path is relative and doesn't traverse up
75
77
  if (pluginRelativePath.startsWith('/') || pluginRelativePath.includes('..')) {
@@ -174,11 +176,14 @@ function resolvePluginPath(pluginSpec, configPath) {
174
176
  try {
175
177
  const packageJsonPath = resolve(process.cwd(), 'node_modules', pluginSpec, 'package.json');
176
178
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
177
- if (packageJson.vizzly?.plugin) {
179
+
180
+ // Support both new `vizzlyPlugin` and legacy `vizzly.plugin`
181
+ const pluginField = packageJson.vizzlyPlugin || packageJson.vizzly?.plugin;
182
+ if (pluginField) {
178
183
  const packageDir = dirname(packageJsonPath);
179
- return resolve(packageDir, packageJson.vizzly.plugin);
184
+ return resolve(packageDir, pluginField);
180
185
  }
181
- throw new Error('Package does not specify a vizzly.plugin field');
186
+ throw new Error('Package does not specify a vizzlyPlugin or vizzly.plugin field');
182
187
  } catch (error) {
183
188
  throw new Error(`Cannot resolve plugin package ${pluginSpec}: ${error.message}`);
184
189
  }
@@ -48,6 +48,10 @@ export const createApiHandler = (client, {
48
48
  let screenshotCount = 0;
49
49
  let uploadPromises = [];
50
50
  const handleScreenshot = async (buildId, name, image, properties = {}, type) => {
51
+ let handlerStart = Date.now();
52
+ output.debug('upload', `${name} received`, {
53
+ buildId: buildId?.slice(0, 8)
54
+ });
51
55
  if (vizzlyDisabled) {
52
56
  output.debug('upload', `${name} (disabled)`);
53
57
  return {
@@ -124,27 +128,39 @@ export const createApiHandler = (client, {
124
128
  };
125
129
  }
126
130
  screenshotCount++;
131
+ let uploadStart = Date.now();
127
132
 
128
133
  // Fire upload in background - DON'T AWAIT!
129
134
  let uploadPromise = uploadScreenshot(client, buildId, name, imageBuffer, properties ?? {}).then(result => {
135
+ let duration = Date.now() - uploadStart;
130
136
  if (!result.skipped) {
131
- output.debug('upload', name);
137
+ output.debug('upload', `${name} completed`, {
138
+ ms: duration
139
+ });
140
+ } else {
141
+ output.debug('upload', `${name} skipped (dedup)`, {
142
+ ms: duration
143
+ });
132
144
  }
133
145
  return {
134
146
  success: true,
135
147
  name,
136
- result
148
+ result,
149
+ duration
137
150
  };
138
151
  }).catch(uploadError => {
152
+ let duration = Date.now() - uploadStart;
139
153
  output.debug('upload', `${name} failed`, {
140
- error: uploadError.message
154
+ error: uploadError.message,
155
+ ms: duration
141
156
  });
142
157
  vizzlyDisabled = true;
143
158
  output.warn('Vizzly disabled due to upload error - continuing tests without visual testing');
144
159
  return {
145
160
  success: false,
146
161
  name,
147
- error: uploadError
162
+ error: uploadError,
163
+ duration
148
164
  };
149
165
  });
150
166
 
@@ -152,6 +168,10 @@ export const createApiHandler = (client, {
152
168
  uploadPromises.push(uploadPromise);
153
169
 
154
170
  // Return immediately - test continues without waiting!
171
+ let handlerMs = Date.now() - handlerStart;
172
+ output.debug('upload', `${name} handler returning`, {
173
+ ms: handlerMs
174
+ });
155
175
  return {
156
176
  statusCode: 200,
157
177
  body: {
@@ -268,6 +268,9 @@ export const createTddHandler = (config, workingDir, baselineBuild, baselineComp
268
268
  }
269
269
  };
270
270
  const handleScreenshot = async (_buildId, name, image, properties = {}, type) => {
271
+ let handlerStart = Date.now();
272
+ output.debug('tdd', `${name} received`);
273
+
271
274
  // Validate and sanitize screenshot name
272
275
  let sanitizedName;
273
276
  try {
@@ -444,6 +447,11 @@ export const createTddHandler = (config, workingDir, baselineBuild, baselineComp
444
447
  }
445
448
 
446
449
  // Match or new baseline
450
+ let handlerMs = Date.now() - handlerStart;
451
+ output.debug('tdd', `${name} handler returning`, {
452
+ ms: handlerMs,
453
+ status: comparison.status
454
+ });
447
455
  return {
448
456
  statusCode: 200,
449
457
  body: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/cli",
3
- "version": "0.24.0",
3
+ "version": "0.24.1",
4
4
  "description": "Visual review platform for UI developers and designers",
5
5
  "keywords": [
6
6
  "visual-testing",