@@ -4,14 +4,36 @@ export function indentNestingLevel(nestingLevel: number) {
44 return ` ${ ' ' . repeat ( nestingLevel ) } ` ;
55}
66
7- export function adjustStringToLength ( message : undefined | string | number , length : number ) {
8- const messageStr = message ? message . toString ( ) : '' ;
9- const messageLen = messageStr . length ;
7+ function valueToPrettyString ( message : NullableTestValue ) : string {
8+ if ( message === undefined ) {
9+ return 'undefined' ;
10+ } else if ( message === null ) {
11+ return 'null' ;
12+ } else if ( typeof message === 'object' ) {
13+ return JSON . stringify ( message ) ;
14+ } else if ( typeof message === 'number' ) {
15+ const digitsAfterDot = message . toString ( ) . split ( '.' ) ?. [ 1 ] ?. length || 0 ;
16+
17+ for ( let i = 0 ; i < digitsAfterDot ; i ++ ) {
18+ if ( Math . abs ( message - Number ( message . toFixed ( i ) ) ) < 0.00001 ) {
19+ return '≈' + message . toFixed ( i ) ;
20+ }
21+ }
22+ return String ( message ) ;
23+ } else {
24+ return message ?. toString ( ) ;
25+ }
26+ }
27+
28+ function adjustValueToLength ( value : NullableTestValue , length : number ) {
29+ const valueStr = valueToPrettyString ( value ) ;
30+
31+ const messageLen = valueStr . length ;
1032 if ( length > messageLen ) {
1133 const indentSize = length - messageLen ;
12- return `${ messageStr } ${ ' ' . repeat ( indentSize ) } ` ;
34+ return `${ valueStr } ${ ' ' . repeat ( indentSize ) } ` ;
1335 } else {
14- return messageStr . slice ( 0 , length ) ;
36+ return valueStr . slice ( 0 , length ) ;
1537 }
1638}
1739
@@ -112,11 +134,87 @@ export function formatString(template: string, variableObject: unknown, index: n
112134 return testName ;
113135}
114136
115- export function formatSnapshotMismatch ( mismatches : Array < Mismatch > , native : boolean ) {
116- /** | HEIGHT | WIDTH |
117- index | EXPECTED | ACTUAL | EXPECTED | ACTUAL |
118- */
137+ const VALUE_COLUMN_WIDTH = 15 ;
138+ const INDEX_COLUMN_WIDTH = 7 ;
139+
140+ const VERTICAL_LINE = '│' ;
141+ const VERTICAL_LINE_DOUBLE = '┃' ;
142+ const HORIZONTAL_LINE = '━' ;
143+
144+ function getBorderLine ( keys : Array < string > , type : 'top' | 'bottom' | 'mid' ) {
145+ const leftEdge = { top : '╭' , mid : '├' , bottom : '╰' } ;
146+ const rightEdge = { top : '╮' , mid : '┤' , bottom : '╯' } ;
147+ const boldLineJoint = { top : '┳' , mid : '╋' , bottom : '┻' } ;
148+ const singleLineJoint = { top : '┯' , mid : '┷' , bottom : HORIZONTAL_LINE } ;
149+
150+ return (
151+ leftEdge [ type ] +
152+ HORIZONTAL_LINE . repeat ( INDEX_COLUMN_WIDTH ) +
153+ boldLineJoint [ type ] +
154+ keys
155+ . map (
156+ _key =>
157+ HORIZONTAL_LINE . repeat ( VALUE_COLUMN_WIDTH ) +
158+ singleLineJoint [ type ] +
159+ HORIZONTAL_LINE . repeat ( VALUE_COLUMN_WIDTH ) ,
160+ )
161+ . join ( boldLineJoint [ type ] ) +
162+ rightEdge [ type ]
163+ ) ;
164+ }
165+
166+ function getUpperTableHeader ( keys : Array < string > ) {
167+ return (
168+ ' ' . repeat ( INDEX_COLUMN_WIDTH ) +
169+ VERTICAL_LINE_DOUBLE +
170+ keys
171+ . map (
172+ key =>
173+ adjustValueToLength ( key , VALUE_COLUMN_WIDTH ) + VERTICAL_LINE + adjustValueToLength ( key , VALUE_COLUMN_WIDTH ) ,
174+ )
175+ . join ( VERTICAL_LINE_DOUBLE )
176+ ) ;
177+ }
119178
179+ function getLowerTableHeader ( keys : Array < string > , native : boolean ) {
180+ const columnPair =
181+ adjustValueToLength ( native ? 'native' : 'expected' , VALUE_COLUMN_WIDTH ) +
182+ VERTICAL_LINE +
183+ adjustValueToLength ( native ? 'js' : 'captured' , VALUE_COLUMN_WIDTH ) ;
184+
185+ return (
186+ adjustValueToLength ( 'index' , INDEX_COLUMN_WIDTH ) +
187+ VERTICAL_LINE_DOUBLE +
188+ keys . map ( _ => columnPair ) . join ( VERTICAL_LINE_DOUBLE )
189+ ) ;
190+ }
191+
192+ function withSideBorders ( line : string ) {
193+ return VERTICAL_LINE + line + VERTICAL_LINE ;
194+ }
195+
196+ function getComparisonRow ( mismatch : Mismatch , keys : Array < string > ) {
197+ const { index, capturedSnapshot, expectedSnapshot } = mismatch ;
198+ const indexColumn = adjustValueToLength ( index . toString ( ) , INDEX_COLUMN_WIDTH ) ;
199+ const formattedCells = keys . map ( key => {
200+ const expectedValue = expectedSnapshot [ key as keyof typeof expectedSnapshot ] ;
201+ const capturedValue = capturedSnapshot [ key as keyof typeof capturedSnapshot ] ;
202+
203+ const match = expectedValue === capturedValue ;
204+
205+ const expectedAdjusted = adjustValueToLength ( expectedValue , VALUE_COLUMN_WIDTH ) ;
206+ const capturedAdjusted = adjustValueToLength ( capturedValue , VALUE_COLUMN_WIDTH ) ;
207+
208+ const expectedColored = match ? expectedAdjusted : green ( expectedAdjusted ) ;
209+ const capturedColored = match ? capturedAdjusted : red ( capturedAdjusted ) ;
210+
211+ return expectedColored + color ( VERTICAL_LINE , 'gray' ) + capturedColored ;
212+ } ) ;
213+
214+ return indexColumn + VERTICAL_LINE_DOUBLE + formattedCells . join ( VERTICAL_LINE_DOUBLE ) ;
215+ }
216+
217+ export function formatSnapshotMismatch ( mismatches : Array < Mismatch > , native : boolean ) {
120218 const keysToPrint : Array < string > = [ ] ;
121219 mismatches . forEach ( ( { expectedSnapshot, capturedSnapshot } ) => {
122220 Object . keys ( expectedSnapshot ) . forEach ( key => {
@@ -131,45 +229,14 @@ export function formatSnapshotMismatch(mismatches: Array<Mismatch>, native: bool
131229 } ) ;
132230 } ) ;
133231
134- const valueColumnWidth = 15 ;
135- const indexColumnWidth = 7 ;
136-
137- const row1 =
138- ' ' . repeat ( indexColumnWidth ) +
139- '|' +
140- keysToPrint . map ( key => adjustStringToLength ( key , 2 * valueColumnWidth + 1 ) ) . join ( '|' ) ;
141-
142- const row2 =
143- adjustStringToLength ( 'index' , indexColumnWidth ) +
144- '|' +
145- keysToPrint
146- . map (
147- _ =>
148- adjustStringToLength ( native ? 'native' : 'expected' , valueColumnWidth ) +
149- '|' +
150- adjustStringToLength ( native ? 'js' : 'captured' , valueColumnWidth ) ,
151- )
152- . join ( '|' ) ;
153-
154- const emptyRow =
155- '-' . repeat ( indexColumnWidth ) +
156- ( '+' + '-' . repeat ( valueColumnWidth ) + '+' + '-' . repeat ( valueColumnWidth ) ) . repeat ( keysToPrint . length ) ;
157-
158- const remainingRows = mismatches . map (
159- ( { index, expectedSnapshot, capturedSnapshot } ) =>
160- adjustStringToLength ( index . toString ( ) , indexColumnWidth ) +
161- '|' +
162- keysToPrint
163- . map (
164- key =>
165- green ( adjustStringToLength ( expectedSnapshot [ key as keyof typeof expectedSnapshot ] , valueColumnWidth ) ) +
166- '|' +
167- red ( adjustStringToLength ( capturedSnapshot [ key as keyof typeof capturedSnapshot ] , valueColumnWidth ) ) ,
168- )
169- . join ( '|' ) ,
170- ) ;
232+ const topLine = getBorderLine ( keysToPrint , 'top' ) ;
233+ const upperHeader = withSideBorders ( getUpperTableHeader ( keysToPrint ) ) ;
234+ const lowerHeader = withSideBorders ( getLowerTableHeader ( keysToPrint , native ) ) ;
235+ const separatorLine = getBorderLine ( keysToPrint , 'mid' ) ;
236+ const mismatchRows = mismatches . map ( mismatch => withSideBorders ( getComparisonRow ( mismatch , keysToPrint ) ) ) ;
237+ const bottomLine = getBorderLine ( keysToPrint , 'bottom' ) ;
171238
172- return [ row1 , row2 , emptyRow , ...remainingRows ] . join ( '\n' ) ;
239+ return [ topLine , upperHeader , lowerHeader , separatorLine , ...mismatchRows , bottomLine ] . join ( '\n' ) ;
173240}
174241
175242export const EMPTY_LOG_PLACEHOLDER = color ( applyMarkdown ( '*** ***' ) , 'lightGray' ) ;
0 commit comments