@vizzly-testing/cli 0.12.0 → 0.13.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.
@@ -14,6 +14,65 @@ export class ServerManager extends BaseService {
14
14
  error: string;
15
15
  details: any;
16
16
  tddMode: boolean;
17
+ originalPath?: undefined;
18
+ filePath?: undefined;
19
+ receivedType?: undefined;
20
+ comparison?: undefined;
21
+ status?: undefined;
22
+ message?: undefined;
23
+ success?: undefined;
24
+ };
25
+ } | {
26
+ statusCode: number;
27
+ body: {
28
+ error: string;
29
+ originalPath: any;
30
+ tddMode: boolean;
31
+ details?: undefined;
32
+ filePath?: undefined;
33
+ receivedType?: undefined;
34
+ comparison?: undefined;
35
+ status?: undefined;
36
+ message?: undefined;
37
+ success?: undefined;
38
+ };
39
+ } | {
40
+ statusCode: number;
41
+ body: {
42
+ error: string;
43
+ filePath: any;
44
+ tddMode: boolean;
45
+ details?: undefined;
46
+ originalPath?: undefined;
47
+ receivedType?: undefined;
48
+ comparison?: undefined;
49
+ status?: undefined;
50
+ message?: undefined;
51
+ success?: undefined;
52
+ };
53
+ } | {
54
+ statusCode: number;
55
+ body: {
56
+ error: string;
57
+ tddMode: boolean;
58
+ details?: undefined;
59
+ originalPath?: undefined;
60
+ filePath?: undefined;
61
+ receivedType?: undefined;
62
+ comparison?: undefined;
63
+ status?: undefined;
64
+ message?: undefined;
65
+ success?: undefined;
66
+ };
67
+ } | {
68
+ statusCode: number;
69
+ body: {
70
+ error: string;
71
+ receivedType: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
72
+ tddMode: boolean;
73
+ details?: undefined;
74
+ originalPath?: undefined;
75
+ filePath?: undefined;
17
76
  comparison?: undefined;
18
77
  status?: undefined;
19
78
  message?: undefined;
@@ -34,6 +93,9 @@ export class ServerManager extends BaseService {
34
93
  threshold: any;
35
94
  };
36
95
  tddMode: boolean;
96
+ originalPath?: undefined;
97
+ filePath?: undefined;
98
+ receivedType?: undefined;
37
99
  status?: undefined;
38
100
  message?: undefined;
39
101
  success?: undefined;
@@ -55,17 +117,9 @@ export class ServerManager extends BaseService {
55
117
  tddMode: boolean;
56
118
  error?: undefined;
57
119
  details?: undefined;
58
- success?: undefined;
59
- };
60
- } | {
61
- statusCode: number;
62
- body: {
63
- error: string;
64
- tddMode: boolean;
65
- details?: undefined;
66
- comparison?: undefined;
67
- status?: undefined;
68
- message?: undefined;
120
+ originalPath?: undefined;
121
+ filePath?: undefined;
122
+ receivedType?: undefined;
69
123
  success?: undefined;
70
124
  };
71
125
  } | {
@@ -84,6 +138,9 @@ export class ServerManager extends BaseService {
84
138
  tddMode: boolean;
85
139
  error?: undefined;
86
140
  details?: undefined;
141
+ originalPath?: undefined;
142
+ filePath?: undefined;
143
+ receivedType?: undefined;
87
144
  status?: undefined;
88
145
  message?: undefined;
89
146
  };
@@ -97,7 +154,7 @@ export class ServerManager extends BaseService {
97
154
  comparisons: any[];
98
155
  baseline: any;
99
156
  }>;
100
- acceptBaseline: (screenshotName: any) => Promise<any>;
157
+ acceptBaseline: (comparisonId: any) => Promise<any>;
101
158
  acceptAllBaselines: () => Promise<{
102
159
  count: number;
103
160
  }>;
@@ -117,16 +174,61 @@ export class ServerManager extends BaseService {
117
174
  count: number;
118
175
  message: string;
119
176
  error?: undefined;
177
+ originalPath?: undefined;
178
+ filePath?: undefined;
179
+ receivedType?: undefined;
180
+ name?: undefined;
181
+ };
182
+ } | {
183
+ statusCode: number;
184
+ body: {
185
+ error: string;
186
+ success?: undefined;
187
+ disabled?: undefined;
188
+ count?: undefined;
189
+ message?: undefined;
190
+ originalPath?: undefined;
191
+ filePath?: undefined;
192
+ receivedType?: undefined;
193
+ name?: undefined;
194
+ };
195
+ } | {
196
+ statusCode: number;
197
+ body: {
198
+ error: string;
199
+ originalPath: any;
200
+ success?: undefined;
201
+ disabled?: undefined;
202
+ count?: undefined;
203
+ message?: undefined;
204
+ filePath?: undefined;
205
+ receivedType?: undefined;
206
+ name?: undefined;
207
+ };
208
+ } | {
209
+ statusCode: number;
210
+ body: {
211
+ error: string;
212
+ filePath: any;
213
+ success?: undefined;
214
+ disabled?: undefined;
215
+ count?: undefined;
216
+ message?: undefined;
217
+ originalPath?: undefined;
218
+ receivedType?: undefined;
120
219
  name?: undefined;
121
220
  };
122
221
  } | {
123
222
  statusCode: number;
124
223
  body: {
125
224
  error: string;
225
+ receivedType: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
126
226
  success?: undefined;
127
227
  disabled?: undefined;
128
228
  count?: undefined;
129
229
  message?: undefined;
230
+ originalPath?: undefined;
231
+ filePath?: undefined;
130
232
  name?: undefined;
131
233
  };
132
234
  } | {
@@ -138,6 +240,9 @@ export class ServerManager extends BaseService {
138
240
  disabled?: undefined;
139
241
  message?: undefined;
140
242
  error?: undefined;
243
+ originalPath?: undefined;
244
+ filePath?: undefined;
245
+ receivedType?: undefined;
141
246
  };
142
247
  }>;
143
248
  getScreenshotCount: () => number;
@@ -22,12 +22,14 @@ export class TddService {
22
22
  handleLocalBaselines(): Promise<any | null>;
23
23
  loadBaseline(): Promise<any>;
24
24
  compareScreenshot(name: any, imageBuffer: any, properties?: {}): Promise<{
25
+ id: any;
25
26
  name: any;
26
27
  status: string;
27
28
  baseline: any;
28
29
  current: any;
29
30
  diff: any;
30
31
  properties: any;
32
+ signature: string;
31
33
  }>;
32
34
  getResults(): {
33
35
  total: number;
@@ -74,9 +76,9 @@ export class TddService {
74
76
  private updateSingleBaseline;
75
77
  /**
76
78
  * Accept a current screenshot as the new baseline
77
- * @param {string} name - Screenshot name to accept
79
+ * @param {string} id - Comparison ID to accept (generated from signature)
78
80
  * @returns {Object} Result object
79
81
  */
80
- acceptBaseline(name: string): any;
82
+ acceptBaseline(id: string): any;
81
83
  }
82
84
  import { ApiService } from '../services/api-service.js';
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @module image-input-detector
3
+ * @description Utilities for detecting whether a string is a base64 image or a file path
4
+ */
5
+ /**
6
+ * Check if a string is valid base64 encoded data
7
+ *
8
+ * Base64 strings consist only of:
9
+ * - A-Z, a-z, 0-9, +, /
10
+ * - Optional padding with = at the end
11
+ * - Must be in groups of 4 characters (with optional 2-3 char group at end with padding)
12
+ *
13
+ * @param {string} str - String to check
14
+ * @returns {boolean} True if the string appears to be valid base64
15
+ *
16
+ * @example
17
+ * isBase64('ZmFrZS1wbmctZGF0YQ==') // true
18
+ * isBase64('./screenshot.png') // false
19
+ * isBase64('/absolute/path.png') // false
20
+ */
21
+ export function isBase64(str: string): boolean;
22
+ /**
23
+ * Check if a string looks like a file path
24
+ *
25
+ * Detects common file path patterns across platforms:
26
+ * - Relative paths: ./file.png, ../file.png, subdirectory/file.png
27
+ * - Absolute Unix paths: /absolute/path/file.png
28
+ * - Absolute Windows paths: C:\path\file.png, C:/path/file.png
29
+ * - File URIs: file:///path/to/file.png
30
+ * - Paths with common image extensions
31
+ *
32
+ * Note: This is heuristic-based and doesn't check file existence
33
+ *
34
+ * @param {string} str - String to check
35
+ * @returns {boolean} True if the string looks like a file path
36
+ *
37
+ * @example
38
+ * looksLikeFilePath('./screenshot.png') // true
39
+ * looksLikeFilePath('/abs/path/file.png') // true
40
+ * looksLikeFilePath('C:\\Windows\\file.png') // true
41
+ * looksLikeFilePath('ZmFrZS1wbmctZGF0YQ==') // false
42
+ */
43
+ export function looksLikeFilePath(str: string): boolean;
44
+ /**
45
+ * Detect the type of image input
46
+ *
47
+ * Determines whether a string input is:
48
+ * - 'base64': Base64 encoded image data
49
+ * - 'file-path': A file path (relative or absolute)
50
+ * - 'unknown': Cannot determine (ambiguous or invalid)
51
+ *
52
+ * Strategy:
53
+ * 1. First check if it's valid base64 (can contain / which might look like paths)
54
+ * 2. Then check if it looks like a file path (more specific patterns)
55
+ * 3. Otherwise return 'unknown'
56
+ *
57
+ * This order prevents base64 strings (which can contain /) from being
58
+ * misidentified as file paths. Base64 validation is stricter and should
59
+ * be checked first.
60
+ *
61
+ * @param {string} str - String to detect
62
+ * @returns {'base64' | 'file-path' | 'unknown'} Detected input type
63
+ *
64
+ * @example
65
+ * detectImageInputType('./screenshot.png') // 'file-path'
66
+ * detectImageInputType('ZmFrZS1wbmctZGF0YQ==') // 'base64'
67
+ * detectImageInputType('data:image/png;base64,iVBOR...') // 'base64'
68
+ * detectImageInputType('C:\\path\\image.png') // 'file-path'
69
+ * detectImageInputType('invalid!!!') // 'unknown'
70
+ */
71
+ export function detectImageInputType(str: string): "base64" | "file-path" | "unknown";
@@ -0,0 +1,150 @@
1
+ /**
2
+ * @module image-input-detector
3
+ * @description Utilities for detecting whether a string is a base64 image or a file path
4
+ */
5
+
6
+ /**
7
+ * Check if a string is valid base64 encoded data
8
+ *
9
+ * Base64 strings consist only of:
10
+ * - A-Z, a-z, 0-9, +, /
11
+ * - Optional padding with = at the end
12
+ * - Must be in groups of 4 characters (with optional 2-3 char group at end with padding)
13
+ *
14
+ * @param {string} str - String to check
15
+ * @returns {boolean} True if the string appears to be valid base64
16
+ *
17
+ * @example
18
+ * isBase64('ZmFrZS1wbmctZGF0YQ==') // true
19
+ * isBase64('./screenshot.png') // false
20
+ * isBase64('/absolute/path.png') // false
21
+ */
22
+ export function isBase64(str) {
23
+ if (typeof str !== 'string' || str.length === 0) {
24
+ return false;
25
+ }
26
+
27
+ // Strip data URI prefix if present (e.g., data:image/png;base64,...)
28
+ let base64Content = str;
29
+ if (str.startsWith('data:')) {
30
+ const match = str.match(/^data:[a-zA-Z0-9+/.-]+;base64,(.+)$/);
31
+ if (!match) {
32
+ return false; // Has data: prefix but invalid format
33
+ }
34
+ base64Content = match[1];
35
+ }
36
+
37
+ // Base64 regex: groups of 4 chars [A-Za-z0-9+/], with optional padding
38
+ // Valid endings: no padding, or 2/3 chars + padding (= or ==)
39
+ const base64Pattern = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
40
+ return base64Pattern.test(base64Content);
41
+ }
42
+
43
+ /**
44
+ * Check if a string looks like a file path
45
+ *
46
+ * Detects common file path patterns across platforms:
47
+ * - Relative paths: ./file.png, ../file.png, subdirectory/file.png
48
+ * - Absolute Unix paths: /absolute/path/file.png
49
+ * - Absolute Windows paths: C:\path\file.png, C:/path/file.png
50
+ * - File URIs: file:///path/to/file.png
51
+ * - Paths with common image extensions
52
+ *
53
+ * Note: This is heuristic-based and doesn't check file existence
54
+ *
55
+ * @param {string} str - String to check
56
+ * @returns {boolean} True if the string looks like a file path
57
+ *
58
+ * @example
59
+ * looksLikeFilePath('./screenshot.png') // true
60
+ * looksLikeFilePath('/abs/path/file.png') // true
61
+ * looksLikeFilePath('C:\\Windows\\file.png') // true
62
+ * looksLikeFilePath('ZmFrZS1wbmctZGF0YQ==') // false
63
+ */
64
+ export function looksLikeFilePath(str) {
65
+ if (typeof str !== 'string' || str.length === 0) {
66
+ return false;
67
+ }
68
+
69
+ // 0. Explicitly reject data URIs first (they contain : and / which would match path patterns)
70
+ if (str.startsWith('data:')) {
71
+ return false;
72
+ }
73
+
74
+ // 1. Check for file:// URI scheme
75
+ if (str.startsWith('file://')) {
76
+ return true;
77
+ }
78
+
79
+ // 2. Check for absolute paths (Unix or Windows)
80
+ // Unix: starts with /
81
+ // Windows: starts with drive letter like C:\ or C:/
82
+ if (str.startsWith('/') || /^[A-Za-z]:[/\\]/.test(str)) {
83
+ return true;
84
+ }
85
+
86
+ // 3. Check for relative path indicators
87
+ // ./ or ../ or .\ or ..\
88
+ if (/^\.\.?[/\\]/.test(str)) {
89
+ return true;
90
+ }
91
+
92
+ // 4. Check for path separators (forward or back slash)
93
+ // This catches paths like: subdirectory/file.png or subdirectory\file.png
94
+ if (/[/\\]/.test(str)) {
95
+ return true;
96
+ }
97
+
98
+ // 5. Check for common image file extensions
99
+ // This catches simple filenames like: screenshot.png
100
+ // Common extensions: png, jpg, jpeg, gif, webp, bmp, svg, tiff, ico
101
+ if (/\.(png|jpe?g|gif|webp|bmp|svg|tiff?|ico)$/i.test(str)) {
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+
107
+ /**
108
+ * Detect the type of image input
109
+ *
110
+ * Determines whether a string input is:
111
+ * - 'base64': Base64 encoded image data
112
+ * - 'file-path': A file path (relative or absolute)
113
+ * - 'unknown': Cannot determine (ambiguous or invalid)
114
+ *
115
+ * Strategy:
116
+ * 1. First check if it's valid base64 (can contain / which might look like paths)
117
+ * 2. Then check if it looks like a file path (more specific patterns)
118
+ * 3. Otherwise return 'unknown'
119
+ *
120
+ * This order prevents base64 strings (which can contain /) from being
121
+ * misidentified as file paths. Base64 validation is stricter and should
122
+ * be checked first.
123
+ *
124
+ * @param {string} str - String to detect
125
+ * @returns {'base64' | 'file-path' | 'unknown'} Detected input type
126
+ *
127
+ * @example
128
+ * detectImageInputType('./screenshot.png') // 'file-path'
129
+ * detectImageInputType('ZmFrZS1wbmctZGF0YQ==') // 'base64'
130
+ * detectImageInputType('data:image/png;base64,iVBOR...') // 'base64'
131
+ * detectImageInputType('C:\\path\\image.png') // 'file-path'
132
+ * detectImageInputType('invalid!!!') // 'unknown'
133
+ */
134
+ export function detectImageInputType(str) {
135
+ if (typeof str !== 'string' || str.length === 0) {
136
+ return 'unknown';
137
+ }
138
+
139
+ // Check base64 FIRST - base64 strings can contain / which looks like paths
140
+ // Base64 validation is stricter and more deterministic
141
+ if (isBase64(str)) {
142
+ return 'base64';
143
+ }
144
+
145
+ // Then check file path - catch patterns that aren't valid base64
146
+ if (looksLikeFilePath(str)) {
147
+ return 'file-path';
148
+ }
149
+ return 'unknown';
150
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Visual review platform for UI developers and designers",
5
5
  "keywords": [
6
6
  "visual-testing",
@@ -72,7 +72,7 @@
72
72
  "format:check": "prettier --check src tests"
73
73
  },
74
74
  "engines": {
75
- "node": ">=20.0.0"
75
+ "node": ">=22.0.0"
76
76
  },
77
77
  "publishConfig": {
78
78
  "access": "public",