Skip to content

Commit 12db071

Browse files
authored
Improve formatting of snapnshot mismatch comparison (#6272)
## Summary The new snapshots: * group columns in pairs * only highlight the values that doesn't match ![image](https://github.com/user-attachments/assets/23c900de-ca75-41fa-a675-8ad974f7ddd0) ![image](https://github.com/user-attachments/assets/a7ba9037-14ca-4afc-a5c6-0669ed61c6cc) ![image](https://github.com/user-attachments/assets/fbc20736-2b61-4401-9f65-4fafecefa5d5) ## Test plan
1 parent a463386 commit 12db071

1 file changed

Lines changed: 114 additions & 47 deletions

File tree

apps/common-app/src/examples/RuntimeTests/ReanimatedRuntimeTestsRunner/stringFormatUtils.ts

Lines changed: 114 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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

175242
export const EMPTY_LOG_PLACEHOLDER = color(applyMarkdown('*** ***'), 'lightGray');

0 commit comments

Comments
 (0)