@vizzly-testing/cli 0.11.2 → 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.
@@ -1,5 +1,7 @@
1
1
  import { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
2
2
  import { join } from 'path';
3
+ import { compare } from '@vizzly-testing/honeydiff';
4
+ import crypto from 'crypto';
3
5
  import { ApiService } from '../services/api-service.js';
4
6
  import { createServiceLogger } from '../utils/logger-factory.js';
5
7
  import { colors } from '../utils/colors.js';
@@ -13,13 +15,26 @@ const logger = createServiceLogger('TDD');
13
15
  /**
14
16
  * Generate a screenshot signature for baseline matching
15
17
  * Uses same logic as screenshot-identity.js: name + viewport_width + browser
18
+ *
19
+ * Matches backend signature generation which uses:
20
+ * - screenshot.name
21
+ * - screenshot.viewport_width (top-level property)
22
+ * - screenshot.browser (top-level property)
16
23
  */
17
24
  function generateScreenshotSignature(name, properties = {}) {
18
25
  let parts = [name];
19
26
 
27
+ // Check for viewport_width as top-level property first (backend format)
28
+ let viewportWidth = properties.viewport_width;
29
+
30
+ // Fallback to nested viewport.width (SDK format)
31
+ if (!viewportWidth && properties.viewport?.width) {
32
+ viewportWidth = properties.viewport.width;
33
+ }
34
+
20
35
  // Add viewport width if present
21
- if (properties.viewport?.width) {
22
- parts.push(properties.viewport.width.toString());
36
+ if (viewportWidth) {
37
+ parts.push(viewportWidth.toString());
23
38
  }
24
39
 
25
40
  // Add browser if present
@@ -37,6 +52,14 @@ function signatureToFilename(signature) {
37
52
  return signature.replace(/\|/g, '_');
38
53
  }
39
54
 
55
+ /**
56
+ * Generate a stable unique ID from signature for TDD comparisons
57
+ * This allows UI to reference specific variants without database IDs
58
+ */
59
+ function generateComparisonId(signature) {
60
+ return crypto.createHash('sha256').update(signature).digest('hex').slice(0, 16);
61
+ }
62
+
40
63
  /**
41
64
  * Create a new TDD service instance
42
65
  */
@@ -133,7 +156,7 @@ export class TddService {
133
156
  }
134
157
  } else if (comparisonId) {
135
158
  // Use specific comparison ID - download only this comparison's baseline screenshot
136
- logger.info(`📌 Using comparison: ${comparisonId}`);
159
+ logger.info(`Using comparison: ${comparisonId}`);
137
160
  const comparison = await this.api.getComparison(comparisonId);
138
161
 
139
162
  // A comparison doesn't have baselineBuild directly - we need to get it
@@ -148,6 +171,38 @@ export class TddService {
148
171
  throw new Error(`Baseline screenshot for comparison ${comparisonId} has no download URL`);
149
172
  }
150
173
 
174
+ // Extract properties from the current screenshot to ensure signature matching
175
+ // The baseline should use the same properties (viewport/browser) as the current screenshot
176
+ // so that generateScreenshotSignature produces the correct filename
177
+ // Use current screenshot properties since we're downloading baseline to compare against current
178
+ let screenshotProperties = {};
179
+
180
+ // Build properties from comparison API fields (added in backend update)
181
+ // Use current_* fields since we're matching against the current screenshot being tested
182
+ if (comparison.current_viewport_width || comparison.current_browser) {
183
+ if (comparison.current_viewport_width) {
184
+ screenshotProperties.viewport = {
185
+ width: comparison.current_viewport_width,
186
+ height: comparison.current_viewport_height
187
+ };
188
+ }
189
+ if (comparison.current_browser) {
190
+ screenshotProperties.browser = comparison.current_browser;
191
+ }
192
+ } else if (comparison.baseline_viewport_width || comparison.baseline_browser) {
193
+ // Fallback to baseline properties if current not available
194
+ if (comparison.baseline_viewport_width) {
195
+ screenshotProperties.viewport = {
196
+ width: comparison.baseline_viewport_width,
197
+ height: comparison.baseline_viewport_height
198
+ };
199
+ }
200
+ if (comparison.baseline_browser) {
201
+ screenshotProperties.browser = comparison.baseline_browser;
202
+ }
203
+ }
204
+ logger.info(`📊 Extracted properties for signature: ${JSON.stringify(screenshotProperties)}`);
205
+
151
206
  // For a specific comparison, we only download that one baseline screenshot
152
207
  // Create a mock build structure with just this one screenshot
153
208
  baselineBuild = {
@@ -157,8 +212,8 @@ export class TddService {
157
212
  id: comparison.baseline_screenshot.id,
158
213
  name: comparison.baseline_name || comparison.current_name,
159
214
  original_url: baselineUrl,
160
- metadata: {},
161
- properties: {}
215
+ metadata: screenshotProperties,
216
+ properties: screenshotProperties
162
217
  }]
163
218
  };
164
219
  } else {
@@ -193,12 +248,6 @@ export class TddService {
193
248
  logger.info(`Using baseline from build: ${colors.cyan(baselineBuild.name || 'Unknown')} (${baselineBuild.id || 'Unknown ID'})`);
194
249
  logger.info(`Checking ${colors.cyan(buildDetails.screenshots.length)} baseline screenshots...`);
195
250
 
196
- // Debug screenshots structure (only in debug mode)
197
- logger.debug(`📊 Screenshots array structure:`, {
198
- screenshotSample: buildDetails.screenshots.slice(0, 2),
199
- totalCount: buildDetails.screenshots.length
200
- });
201
-
202
251
  // Check existing baseline metadata for efficient SHA comparison
203
252
  const existingBaseline = await this.loadBaseline();
204
253
  const existingShaMap = new Map();
@@ -479,6 +528,12 @@ export class TddService {
479
528
  validatedProperties = {};
480
529
  }
481
530
 
531
+ // Normalize properties to match backend format (viewport_width at top level)
532
+ // This ensures signature generation matches backend's screenshot-identity.js
533
+ if (validatedProperties.viewport?.width && !validatedProperties.viewport_width) {
534
+ validatedProperties.viewport_width = validatedProperties.viewport.width;
535
+ }
536
+
482
537
  // Generate signature for baseline matching (name + viewport_width + browser)
483
538
  const signature = generateScreenshotSignature(sanitizedName, validatedProperties);
484
539
  const filename = signatureToFilename(signature);
@@ -536,12 +591,14 @@ export class TddService {
536
591
  writeFileSync(metadataPath, JSON.stringify(this.baselineData, null, 2));
537
592
  logger.debug(`✅ Created baseline for ${sanitizedName}`);
538
593
  const result = {
594
+ id: generateComparisonId(signature),
539
595
  name: sanitizedName,
540
596
  status: 'new',
541
597
  baseline: baselineImagePath,
542
598
  current: currentImagePath,
543
599
  diff: null,
544
- properties: validatedProperties
600
+ properties: validatedProperties,
601
+ signature
545
602
  };
546
603
  this.comparisons.push(result);
547
604
  return result;
@@ -549,55 +606,71 @@ export class TddService {
549
606
 
550
607
  // Baseline exists - compare with it
551
608
  try {
552
- // Use odiff Node.js API to compare images
553
- const {
554
- compare
555
- } = await import('odiff-bin');
556
-
557
609
  // Log file sizes for debugging
558
610
  const baselineSize = readFileSync(baselineImagePath).length;
559
611
  const currentSize = readFileSync(currentImagePath).length;
560
612
  logger.debug(`Comparing ${sanitizedName}`);
561
613
  logger.debug(`Baseline: ${baselineImagePath} (${baselineSize} bytes)`);
562
614
  logger.debug(`Current: ${currentImagePath} (${currentSize} bytes)`);
563
- const result = await compare(baselineImagePath, currentImagePath, diffImagePath, {
564
- threshold: this.threshold,
565
- outputDiffMask: true,
566
- failOnLayoutDiff: true // Fail if image dimensions differ
615
+
616
+ // Try to compare - honeydiff will throw if dimensions don't match
617
+ const result = await compare(baselineImagePath, currentImagePath, {
618
+ colorThreshold: this.threshold,
619
+ // YIQ color threshold (0.0-1.0), default 0.1
620
+ antialiasing: true,
621
+ diffPath: diffImagePath,
622
+ overwrite: true,
623
+ includeClusters: true // Enable spatial clustering analysis
567
624
  });
568
- if (result.match) {
625
+ if (!result.isDifferent) {
569
626
  // Images match
570
627
  const comparison = {
628
+ id: generateComparisonId(signature),
571
629
  name: sanitizedName,
572
630
  status: 'passed',
573
631
  baseline: baselineImagePath,
574
632
  current: currentImagePath,
575
633
  diff: null,
576
634
  properties: validatedProperties,
577
- threshold: this.threshold
635
+ signature,
636
+ threshold: this.threshold,
637
+ // Include honeydiff metrics even for passing comparisons
638
+ totalPixels: result.totalPixels,
639
+ aaPixelsIgnored: result.aaPixelsIgnored,
640
+ aaPercentage: result.aaPercentage
578
641
  };
579
642
  logger.debug(`PASSED ${sanitizedName}`);
580
643
  this.comparisons.push(comparison);
581
644
  return comparison;
582
645
  } else {
583
646
  // Images differ
584
- let diffInfo = '';
585
- if (result.reason === 'pixel-diff') {
586
- diffInfo = ` (${result.diffPercentage.toFixed(2)}% different, ${result.diffCount} pixels)`;
587
- } else if (result.reason === 'layout-diff') {
588
- diffInfo = ' (layout difference)';
647
+ let diffInfo = ` (${result.diffPercentage.toFixed(2)}% different, ${result.diffPixels} pixels)`;
648
+
649
+ // Add cluster info to log if available
650
+ if (result.diffClusters && result.diffClusters.length > 0) {
651
+ diffInfo += `, ${result.diffClusters.length} region${result.diffClusters.length > 1 ? 's' : ''}`;
589
652
  }
590
653
  const comparison = {
654
+ id: generateComparisonId(signature),
591
655
  name: sanitizedName,
592
656
  status: 'failed',
593
657
  baseline: baselineImagePath,
594
658
  current: currentImagePath,
595
659
  diff: diffImagePath,
596
660
  properties: validatedProperties,
661
+ signature,
597
662
  threshold: this.threshold,
598
- diffPercentage: result.reason === 'pixel-diff' ? result.diffPercentage : null,
599
- diffCount: result.reason === 'pixel-diff' ? result.diffCount : null,
600
- reason: result.reason
663
+ diffPercentage: result.diffPercentage,
664
+ diffCount: result.diffPixels,
665
+ reason: 'pixel-diff',
666
+ // Honeydiff metrics
667
+ totalPixels: result.totalPixels,
668
+ aaPixelsIgnored: result.aaPixelsIgnored,
669
+ aaPercentage: result.aaPercentage,
670
+ boundingBox: result.boundingBox,
671
+ heightDiff: result.heightDiff,
672
+ intensityStats: result.intensityStats,
673
+ diffClusters: result.diffClusters
601
674
  };
602
675
  logger.warn(`❌ ${colors.red('FAILED')} ${sanitizedName} - differences detected${diffInfo}`);
603
676
  logger.info(` Diff saved to: ${diffImagePath}`);
@@ -605,15 +678,69 @@ export class TddService {
605
678
  return comparison;
606
679
  }
607
680
  } catch (error) {
608
- // Handle file errors or other issues
681
+ // Check if error is due to dimension mismatch
682
+ const isDimensionMismatch = error.message && error.message.includes("Image dimensions don't match");
683
+ if (isDimensionMismatch) {
684
+ // Different dimensions = different screenshot signature
685
+ // This shouldn't happen if signatures are working correctly, but handle gracefully
686
+ logger.warn(`⚠️ Dimension mismatch for ${sanitizedName} - baseline file exists but has different dimensions`);
687
+ logger.warn(` This indicates a signature collision. Creating new baseline with correct signature.`);
688
+ logger.debug(` Error: ${error.message}`);
689
+
690
+ // Create a new baseline for this screenshot (overwriting the incorrect one)
691
+ writeFileSync(baselineImagePath, imageBuffer);
692
+
693
+ // Update baseline metadata
694
+ if (!this.baselineData) {
695
+ this.baselineData = {
696
+ buildId: 'local-baseline',
697
+ buildName: 'Local TDD Baseline',
698
+ environment: 'test',
699
+ branch: 'local',
700
+ threshold: this.threshold,
701
+ screenshots: []
702
+ };
703
+ }
704
+ const screenshotEntry = {
705
+ name: sanitizedName,
706
+ properties: validatedProperties,
707
+ path: baselineImagePath,
708
+ signature: signature
709
+ };
710
+ const existingIndex = this.baselineData.screenshots.findIndex(s => s.signature === signature);
711
+ if (existingIndex >= 0) {
712
+ this.baselineData.screenshots[existingIndex] = screenshotEntry;
713
+ } else {
714
+ this.baselineData.screenshots.push(screenshotEntry);
715
+ }
716
+ const metadataPath = join(this.baselinePath, 'metadata.json');
717
+ writeFileSync(metadataPath, JSON.stringify(this.baselineData, null, 2));
718
+ logger.info(`✅ Created new baseline for ${sanitizedName} (different dimensions)`);
719
+ const comparison = {
720
+ id: generateComparisonId(signature),
721
+ name: sanitizedName,
722
+ status: 'new',
723
+ baseline: baselineImagePath,
724
+ current: currentImagePath,
725
+ diff: null,
726
+ properties: validatedProperties,
727
+ signature
728
+ };
729
+ this.comparisons.push(comparison);
730
+ return comparison;
731
+ }
732
+
733
+ // Handle other file errors or issues
609
734
  logger.error(`❌ Error comparing ${sanitizedName}: ${error.message}`);
610
735
  const comparison = {
736
+ id: generateComparisonId(signature),
611
737
  name: sanitizedName,
612
738
  status: 'error',
613
739
  baseline: baselineImagePath,
614
740
  current: currentImagePath,
615
741
  diff: null,
616
742
  properties: validatedProperties,
743
+ signature,
617
744
  error: error.message
618
745
  };
619
746
  this.comparisons.push(comparison);
@@ -858,12 +985,14 @@ export class TddService {
858
985
  const metadataPath = join(this.baselinePath, 'metadata.json');
859
986
  writeFileSync(metadataPath, JSON.stringify(this.baselineData, null, 2));
860
987
  const result = {
988
+ id: generateComparisonId(signature),
861
989
  name,
862
990
  status: 'new',
863
991
  baseline: baselineImagePath,
864
992
  current: currentImagePath,
865
993
  diff: null,
866
- properties
994
+ properties,
995
+ signature
867
996
  };
868
997
  this.comparisons.push(result);
869
998
  logger.info(`✅ Baseline created for ${name}`);
@@ -913,12 +1042,14 @@ export class TddService {
913
1042
  const metadataPath = join(this.baselinePath, 'metadata.json');
914
1043
  writeFileSync(metadataPath, JSON.stringify(this.baselineData, null, 2));
915
1044
  const result = {
1045
+ id: generateComparisonId(signature),
916
1046
  name,
917
1047
  status: 'baseline-updated',
918
1048
  baseline: baselineImagePath,
919
1049
  current: currentImagePath,
920
1050
  diff: null,
921
- properties
1051
+ properties,
1052
+ signature
922
1053
  };
923
1054
  this.comparisons.push(result);
924
1055
  logger.info(`🐻 Baseline set for ${name}`);
@@ -927,55 +1058,45 @@ export class TddService {
927
1058
 
928
1059
  /**
929
1060
  * Accept a current screenshot as the new baseline
930
- * @param {string} name - Screenshot name to accept
1061
+ * @param {string} id - Comparison ID to accept (generated from signature)
931
1062
  * @returns {Object} Result object
932
1063
  */
933
- async acceptBaseline(name) {
934
- const sanitizedName = sanitizeScreenshotName(name);
935
- logger.debug(`Starting accept baseline for: ${sanitizedName}`);
936
-
937
- // Find the comparison to get properties
938
- let comparison = this.comparisons.find(c => c.name === sanitizedName);
1064
+ async acceptBaseline(id) {
1065
+ // Find the comparison by ID
1066
+ let comparison = this.comparisons.find(c => c.id === id);
939
1067
  if (!comparison) {
940
- throw new Error(`No comparison found for screenshot: ${name}`);
1068
+ throw new Error(`No comparison found with ID: ${id}`);
941
1069
  }
1070
+ const sanitizedName = comparison.name;
942
1071
  let properties = comparison.properties || {};
943
1072
  let signature = generateScreenshotSignature(sanitizedName, properties);
944
1073
  let filename = signatureToFilename(signature);
945
1074
 
946
1075
  // Find the current screenshot file
947
1076
  const currentImagePath = safePath(this.currentPath, `${filename}.png`);
948
- logger.debug(`Looking for current screenshot at: ${currentImagePath}`);
949
1077
  if (!existsSync(currentImagePath)) {
950
1078
  logger.error(`Current screenshot not found at: ${currentImagePath}`);
951
- throw new Error(`Current screenshot not found: ${name} (looked at ${currentImagePath})`);
1079
+ throw new Error(`Current screenshot not found: ${sanitizedName} (looked at ${currentImagePath})`);
952
1080
  }
953
1081
 
954
1082
  // Read the current image
955
1083
  const imageBuffer = readFileSync(currentImagePath);
956
- logger.debug(`Read current image: ${imageBuffer.length} bytes`);
957
1084
 
958
1085
  // Create baseline directory if it doesn't exist
959
1086
  if (!existsSync(this.baselinePath)) {
960
1087
  mkdirSync(this.baselinePath, {
961
1088
  recursive: true
962
1089
  });
963
- logger.debug(`Created baseline directory: ${this.baselinePath}`);
964
1090
  }
965
1091
 
966
1092
  // Update the baseline
967
1093
  const baselineImagePath = safePath(this.baselinePath, `${filename}.png`);
968
- logger.debug(`Writing baseline to: ${baselineImagePath}`);
969
1094
 
970
1095
  // Write the baseline image directly
971
1096
  writeFileSync(baselineImagePath, imageBuffer);
972
- logger.debug(`Wrote baseline image: ${imageBuffer.length} bytes`);
973
1097
 
974
1098
  // Verify the write
975
- if (existsSync(baselineImagePath)) {
976
- const writtenSize = readFileSync(baselineImagePath).length;
977
- logger.debug(`Verified baseline file exists: ${writtenSize} bytes`);
978
- } else {
1099
+ if (!existsSync(baselineImagePath)) {
979
1100
  logger.error(`Baseline file does not exist after write!`);
980
1101
  }
981
1102
 
@@ -989,7 +1110,6 @@ export class TddService {
989
1110
  threshold: this.threshold,
990
1111
  screenshots: []
991
1112
  };
992
- logger.debug(`Created new baseline metadata`);
993
1113
  }
994
1114
 
995
1115
  // Add or update screenshot in baseline metadata
@@ -1002,17 +1122,13 @@ export class TddService {
1002
1122
  const existingIndex = this.baselineData.screenshots.findIndex(s => s.signature === signature);
1003
1123
  if (existingIndex >= 0) {
1004
1124
  this.baselineData.screenshots[existingIndex] = screenshotEntry;
1005
- logger.debug(`Updated existing metadata entry at index ${existingIndex}`);
1006
1125
  } else {
1007
1126
  this.baselineData.screenshots.push(screenshotEntry);
1008
- logger.debug(`Added new metadata entry (total: ${this.baselineData.screenshots.length})`);
1009
1127
  }
1010
1128
 
1011
1129
  // Save updated metadata
1012
1130
  const metadataPath = join(this.baselinePath, 'metadata.json');
1013
1131
  writeFileSync(metadataPath, JSON.stringify(this.baselineData, null, 2));
1014
- logger.debug(`Saved metadata to: ${metadataPath}`);
1015
- logger.debug(`Accepted ${sanitizedName} as new baseline`);
1016
1132
  return {
1017
1133
  name: sanitizedName,
1018
1134
  status: 'accepted',
@@ -1,6 +1,7 @@
1
- export default function ComparisonCard({ comparison, onAccept, onReject, userAction, }: {
1
+ export default function ComparisonCard({ comparison, onAccept, onReject, userAction, variantSelector, }: {
2
2
  comparison: any;
3
3
  onAccept: any;
4
4
  onReject: any;
5
5
  userAction: any;
6
+ variantSelector?: any;
6
7
  }): any;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Comparison group component that displays multiple variants of the same screenshot
3
+ * Matches cloud product's grouped screenshot display
4
+ */
5
+ export default function ComparisonGroup({ group, onAccept, onReject, loadingStates, }: {
6
+ group: any;
7
+ onAccept: any;
8
+ onReject: any;
9
+ loadingStates: any;
10
+ }): any;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Variant selector for toggling between different viewport sizes and browsers
3
+ * Matches cloud product's variant selection UI
4
+ */
5
+ export default function VariantSelector({ group, selectedIndex, onSelect }: {
6
+ group: any;
7
+ selectedIndex: any;
8
+ onSelect: any;
9
+ }): any;
@@ -1,4 +1,4 @@
1
1
  export function fetchReportData(): Promise<any>;
2
- export function acceptBaseline(screenshotName: any): Promise<any>;
2
+ export function acceptBaseline(comparisonId: any): Promise<any>;
3
3
  export function acceptAllBaselines(): Promise<any>;
4
4
  export function resetBaselines(): Promise<any>;
@@ -7,6 +7,9 @@ export function createApiHandler(apiService: any): {
7
7
  count: number;
8
8
  message: string;
9
9
  error?: undefined;
10
+ originalPath?: undefined;
11
+ filePath?: undefined;
12
+ receivedType?: undefined;
10
13
  name?: undefined;
11
14
  };
12
15
  } | {
@@ -17,6 +20,48 @@ export function createApiHandler(apiService: any): {
17
20
  disabled?: undefined;
18
21
  count?: undefined;
19
22
  message?: undefined;
23
+ originalPath?: undefined;
24
+ filePath?: undefined;
25
+ receivedType?: undefined;
26
+ name?: undefined;
27
+ };
28
+ } | {
29
+ statusCode: number;
30
+ body: {
31
+ error: string;
32
+ originalPath: any;
33
+ success?: undefined;
34
+ disabled?: undefined;
35
+ count?: undefined;
36
+ message?: undefined;
37
+ filePath?: undefined;
38
+ receivedType?: undefined;
39
+ name?: undefined;
40
+ };
41
+ } | {
42
+ statusCode: number;
43
+ body: {
44
+ error: string;
45
+ filePath: any;
46
+ success?: undefined;
47
+ disabled?: undefined;
48
+ count?: undefined;
49
+ message?: undefined;
50
+ originalPath?: undefined;
51
+ receivedType?: undefined;
52
+ name?: undefined;
53
+ };
54
+ } | {
55
+ statusCode: number;
56
+ body: {
57
+ error: string;
58
+ receivedType: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
59
+ success?: undefined;
60
+ disabled?: undefined;
61
+ count?: undefined;
62
+ message?: undefined;
63
+ originalPath?: undefined;
64
+ filePath?: undefined;
20
65
  name?: undefined;
21
66
  };
22
67
  } | {
@@ -28,6 +73,9 @@ export function createApiHandler(apiService: any): {
28
73
  disabled?: undefined;
29
74
  message?: undefined;
30
75
  error?: undefined;
76
+ originalPath?: undefined;
77
+ filePath?: undefined;
78
+ receivedType?: undefined;
31
79
  };
32
80
  }>;
33
81
  getScreenshotCount: () => number;
@@ -6,6 +6,65 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
6
6
  error: string;
7
7
  details: any;
8
8
  tddMode: boolean;
9
+ originalPath?: undefined;
10
+ filePath?: undefined;
11
+ receivedType?: undefined;
12
+ comparison?: undefined;
13
+ status?: undefined;
14
+ message?: undefined;
15
+ success?: undefined;
16
+ };
17
+ } | {
18
+ statusCode: number;
19
+ body: {
20
+ error: string;
21
+ originalPath: any;
22
+ tddMode: boolean;
23
+ details?: undefined;
24
+ filePath?: undefined;
25
+ receivedType?: undefined;
26
+ comparison?: undefined;
27
+ status?: undefined;
28
+ message?: undefined;
29
+ success?: undefined;
30
+ };
31
+ } | {
32
+ statusCode: number;
33
+ body: {
34
+ error: string;
35
+ filePath: any;
36
+ tddMode: boolean;
37
+ details?: undefined;
38
+ originalPath?: undefined;
39
+ receivedType?: undefined;
40
+ comparison?: undefined;
41
+ status?: undefined;
42
+ message?: undefined;
43
+ success?: undefined;
44
+ };
45
+ } | {
46
+ statusCode: number;
47
+ body: {
48
+ error: string;
49
+ tddMode: boolean;
50
+ details?: undefined;
51
+ originalPath?: undefined;
52
+ filePath?: undefined;
53
+ receivedType?: undefined;
54
+ comparison?: undefined;
55
+ status?: undefined;
56
+ message?: undefined;
57
+ success?: undefined;
58
+ };
59
+ } | {
60
+ statusCode: number;
61
+ body: {
62
+ error: string;
63
+ receivedType: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
64
+ tddMode: boolean;
65
+ details?: undefined;
66
+ originalPath?: undefined;
67
+ filePath?: undefined;
9
68
  comparison?: undefined;
10
69
  status?: undefined;
11
70
  message?: undefined;
@@ -26,6 +85,9 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
26
85
  threshold: any;
27
86
  };
28
87
  tddMode: boolean;
88
+ originalPath?: undefined;
89
+ filePath?: undefined;
90
+ receivedType?: undefined;
29
91
  status?: undefined;
30
92
  message?: undefined;
31
93
  success?: undefined;
@@ -47,17 +109,9 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
47
109
  tddMode: boolean;
48
110
  error?: undefined;
49
111
  details?: undefined;
50
- success?: undefined;
51
- };
52
- } | {
53
- statusCode: number;
54
- body: {
55
- error: string;
56
- tddMode: boolean;
57
- details?: undefined;
58
- comparison?: undefined;
59
- status?: undefined;
60
- message?: undefined;
112
+ originalPath?: undefined;
113
+ filePath?: undefined;
114
+ receivedType?: undefined;
61
115
  success?: undefined;
62
116
  };
63
117
  } | {
@@ -76,6 +130,9 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
76
130
  tddMode: boolean;
77
131
  error?: undefined;
78
132
  details?: undefined;
133
+ originalPath?: undefined;
134
+ filePath?: undefined;
135
+ receivedType?: undefined;
79
136
  status?: undefined;
80
137
  message?: undefined;
81
138
  };
@@ -89,7 +146,7 @@ export function createTddHandler(config: any, workingDir: any, baselineBuild: an
89
146
  comparisons: any[];
90
147
  baseline: any;
91
148
  }>;
92
- acceptBaseline: (screenshotName: any) => Promise<any>;
149
+ acceptBaseline: (comparisonId: any) => Promise<any>;
93
150
  acceptAllBaselines: () => Promise<{
94
151
  count: number;
95
152
  }>;