feat: truncate large object / array / string (#118)

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
This commit is contained in:
Tony Gorez 2021-12-14 15:37:36 +01:00 committed by GitHub
parent d67b9a00b9
commit 03a8ea033a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 30 deletions

View File

@ -4,7 +4,7 @@
import c from 'picocolors'
import type { Formatter } from 'picocolors/types'
import { format as prettyFormat, plugins as prettyFormatPlugins } from 'pretty-format'
import { generateDiff } from '../../reporters/error'
import { unifiedDiff } from '../../reporters/error'
export const EXPECTED_COLOR = c.green
export const RECEIVED_COLOR = c.red
@ -168,5 +168,5 @@ export type DiffOptions = {
// TODO do something with options
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function diff(a: any, b: any, options?: DiffOptions) {
return generateDiff(stringify(a), stringify(b))
return unifiedDiff(stringify(a), stringify(b))
}

View File

@ -80,7 +80,7 @@ async function getSourcePos(ctx: Vitest, nearest: ParsedStack) {
// TODO: handle big object and big string diff
function displayDiff(actual: string, expected: string) {
console.error(c.gray(generateDiff(stringify(actual), stringify(expected))))
console.error(c.gray(unifiedDiff(stringify(actual), stringify(expected))))
}
function printErrorMessage(error: ErrorWithDiff) {
@ -262,28 +262,6 @@ function parseStack(stack: string): ParsedStack[] {
return stackFrames.filter(notNullish)
}
/**
* Returns a diff between 2 strings with coloured ANSI output.
*
* @description
* The diff will be either inline or unified dependent on the value
* of `Base.inlineDiff`.
*
* @param {string} actual
* @param {string} expected
* @return {string} Diff
*/
export function generateDiff(actual: any, expected: any) {
const diffSize = 2048
if (actual.length > diffSize)
actual = `${actual.substring(0, diffSize)} ... Lines skipped`
if (expected.length > diffSize)
expected = `${expected.substring(0, diffSize)} ... Lines skipped`
return unifiedDiff(actual, expected)
}
/**
* Returns unified diff between two strings with coloured ANSI output.
*
@ -292,13 +270,27 @@ export function generateDiff(actual: any, expected: any) {
* @param {String} expected
* @return {string} The diff.
*/
function unifiedDiff(actual: any, expected: any) {
export function unifiedDiff(actual: any, expected: any) {
const diffLimit = 10
const indent = ' '
let expectedLinesCount = 0
let actualLinesCount = 0
function cleanUp(line: string) {
if (line[0] === '+')
return indent + c.green(`${line[0]}${line.slice(1)}`)
if (line[0] === '-')
return indent + c.red(`${line[0]}${line.slice(1)}`)
if (line[0] === '+') {
if (expectedLinesCount >= diffLimit) return
expectedLinesCount++
const isLastLine = expectedLinesCount === diffLimit
return indent + c.green(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ''}`)
}
if (line[0] === '-') {
if (actualLinesCount >= diffLimit) return
actualLinesCount++
const isLastLine = actualLinesCount === diffLimit
return indent + c.red(`${formatLine(line)} ${isLastLine ? renderTruncateMessage(indent) : ''}`)
}
if (line.match(/@@/))
return '--'
if (line.match(/\\ No newline/))
@ -313,6 +305,17 @@ function unifiedDiff(actual: any, expected: any) {
)
}
function formatLine(line: string) {
const lineLimitLength = 50
if (line.length > lineLimitLength)
return `${line.slice(0, lineLimitLength)} ${c.dim('[...truncated]')}`
return line
}
function renderTruncateMessage(indent: string) {
return `\n${indent}${c.dim('[...truncated]')}`
}
function notBlank(line: any) {
return typeof line !== 'undefined' && line !== null
}

View File

@ -10,3 +10,56 @@ Object {
},
}
`;
exports[`snapshot with big array 1`] = `
Object {
"this": Object {
"is": Set {
"one",
Array [
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
Object {},
],
},
},
}
`;
exports[`snapshot with big string 1`] = `
Object {
"this": Object {
"is": Set {
"one",
"zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo,zoo",
},
},
}
`;

View File

@ -16,3 +16,15 @@ Object {
},
}`)
})
test('snapshot with big array', () => {
expect({
this: { is: new Set(['one', new Array(30).fill({})]) },
}).toMatchSnapshot()
})
test('snapshot with big string', () => {
expect({
this: { is: new Set(['one', new Array(30).fill('zoo').join()]) },
}).toMatchSnapshot()
})