mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
(cherry picked from commit e378c0d890
)
Co-authored-by: Spencer <spencer@elastic.co>
This commit is contained in:
parent
fa4d99e26f
commit
8e34004edb
7 changed files with 211 additions and 174 deletions
|
@ -55,11 +55,13 @@ RUNTIME_DEPS = [
|
|||
"@npm//exit-hook",
|
||||
"@npm//getopts",
|
||||
"@npm//globby",
|
||||
"@npm//jest-diff",
|
||||
"@npm//load-json-file",
|
||||
"@npm//markdown-it",
|
||||
"@npm//normalize-path",
|
||||
"@npm//prettier",
|
||||
"@npm//rxjs",
|
||||
"@npm//strip-ansi",
|
||||
"@npm//sort-package-json",
|
||||
"@npm//tar",
|
||||
"@npm//tree-kill",
|
||||
|
@ -90,8 +92,10 @@ TYPES_DEPS = [
|
|||
"@npm//execa",
|
||||
"@npm//exit-hook",
|
||||
"@npm//getopts",
|
||||
"@npm//jest-diff",
|
||||
"@npm//rxjs",
|
||||
"@npm//sort-package-json",
|
||||
"@npm//strip-ansi",
|
||||
"@npm//tree-kill",
|
||||
]
|
||||
|
||||
|
|
106
packages/kbn-dev-utils/src/diff_strings.test.ts
Normal file
106
packages/kbn-dev-utils/src/diff_strings.test.ts
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { diffStrings } from './diff_strings';
|
||||
|
||||
const json = (x: any) => JSON.stringify(x, null, 2);
|
||||
|
||||
describe('diffStrings()', () => {
|
||||
it('returns undefined if values are equal', () => {
|
||||
expect(diffStrings('1', '1')).toBe(undefined);
|
||||
expect(diffStrings(json(['1', '2', { a: 'b' }]), json(['1', '2', { a: 'b' }]))).toBe(undefined);
|
||||
expect(
|
||||
diffStrings(
|
||||
json({
|
||||
a: '1',
|
||||
b: '2',
|
||||
}),
|
||||
json({
|
||||
a: '1',
|
||||
b: '2',
|
||||
})
|
||||
)
|
||||
).toBe(undefined);
|
||||
});
|
||||
|
||||
it('returns a diff if the values are different', () => {
|
||||
const diff = diffStrings(json(['1', '2', { a: 'b' }]), json(['1', '2', { b: 'a' }]));
|
||||
|
||||
expect(diff).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m [[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"2\\",[22m
|
||||
[2m {[22m
|
||||
[32m- \\"a\\": \\"b\\"[39m
|
||||
[31m+ \\"b\\": \\"a\\"[39m
|
||||
[2m }[22m
|
||||
[2m ][22m"
|
||||
`);
|
||||
|
||||
const diff2 = diffStrings(
|
||||
json({
|
||||
a: '1',
|
||||
b: '1',
|
||||
}),
|
||||
json({
|
||||
b: '2',
|
||||
a: '2',
|
||||
})
|
||||
);
|
||||
|
||||
expect(diff2).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m {[22m
|
||||
[32m- \\"a\\": \\"1\\",[39m
|
||||
[32m- \\"b\\": \\"1\\"[39m
|
||||
[31m+ \\"b\\": \\"2\\",[39m
|
||||
[31m+ \\"a\\": \\"2\\"[39m
|
||||
[2m }[22m"
|
||||
`);
|
||||
});
|
||||
|
||||
it('formats large diffs to focus on the changed lines', () => {
|
||||
const diff = diffStrings(
|
||||
json({
|
||||
a: ['1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', '1', '1', '1', '1', '1', '1'],
|
||||
}),
|
||||
json({
|
||||
b: ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', '1'],
|
||||
})
|
||||
);
|
||||
|
||||
expect(diff).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m {[22m
|
||||
[32m- \\"a\\": [[39m
|
||||
[31m+ \\"b\\": [[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[32m- \\"2\\",[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[31m+ \\"2\\",[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m"
|
||||
`);
|
||||
});
|
||||
});
|
97
packages/kbn-dev-utils/src/diff_strings.ts
Normal file
97
packages/kbn-dev-utils/src/diff_strings.ts
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import jestDiff from 'jest-diff';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
import Chalk from 'chalk';
|
||||
|
||||
function reformatJestDiff(diff: string) {
|
||||
const diffLines = diff.split('\n');
|
||||
|
||||
if (
|
||||
diffLines.length < 4 ||
|
||||
stripAnsi(diffLines[0]) !== '- Expected' ||
|
||||
stripAnsi(diffLines[1]) !== '+ Received'
|
||||
) {
|
||||
throw new Error(`unexpected diff format: ${diff}`);
|
||||
}
|
||||
|
||||
const outputLines = [diffLines.shift(), diffLines.shift(), diffLines.shift()];
|
||||
|
||||
/**
|
||||
* buffer which contains between 0 and 5 lines from the diff which aren't additions or
|
||||
* deletions. The first three are the first three lines seen since the buffer was cleared
|
||||
* and the last two lines are the last two lines seen.
|
||||
*
|
||||
* When flushContext() is called we write the first two lines to output, an elipses if there
|
||||
* are five lines, and then the last two lines.
|
||||
*
|
||||
* At the very end we will write the last two lines of context if they're defined
|
||||
*/
|
||||
const contextBuffer: string[] = [];
|
||||
|
||||
/**
|
||||
* Convert a line to an empty line with elipses placed where the text on that line starts
|
||||
*/
|
||||
const toElipses = (line: string) => {
|
||||
return stripAnsi(line).replace(/^(\s*).*/, '$1...');
|
||||
};
|
||||
|
||||
while (diffLines.length) {
|
||||
const line = diffLines.shift()!;
|
||||
const plainLine = stripAnsi(line);
|
||||
if (plainLine.startsWith('+ ') || plainLine.startsWith('- ')) {
|
||||
// write contextBuffer to the outputLines
|
||||
if (contextBuffer.length) {
|
||||
outputLines.push(
|
||||
...contextBuffer.slice(0, 2),
|
||||
...(contextBuffer.length === 5
|
||||
? [Chalk.dim(toElipses(contextBuffer[2])), ...contextBuffer.slice(3, 5)]
|
||||
: contextBuffer.slice(2, 4))
|
||||
);
|
||||
|
||||
contextBuffer.length = 0;
|
||||
}
|
||||
|
||||
// add this line to the outputLines
|
||||
outputLines.push(line);
|
||||
} else {
|
||||
// update the contextBuffer with this line which doesn't represent a change
|
||||
if (contextBuffer.length === 5) {
|
||||
contextBuffer[3] = contextBuffer[4];
|
||||
contextBuffer[4] = line;
|
||||
} else {
|
||||
contextBuffer.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contextBuffer.length) {
|
||||
outputLines.push(
|
||||
...contextBuffer.slice(0, 2),
|
||||
...(contextBuffer.length > 2 ? [Chalk.dim(toElipses(contextBuffer[2]))] : [])
|
||||
);
|
||||
}
|
||||
|
||||
return outputLines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a diff string which is nicely formatted to show the differences between two strings. This will
|
||||
* be a multi-line string so it's generally a good idea to include a `\n` before this first line of the diff
|
||||
* if you are concatenating it with another message.
|
||||
*/
|
||||
export function diffStrings(expected: string, received: string) {
|
||||
const diff = jestDiff(expected, received);
|
||||
|
||||
if (!diff || stripAnsi(diff) === 'Compared values have no visual difference.') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return reformatJestDiff(diff);
|
||||
}
|
|
@ -33,3 +33,4 @@ export * from './babel';
|
|||
export * from './extract';
|
||||
export * from './vscode_config';
|
||||
export * from './sort_package_json';
|
||||
export * from './diff_strings';
|
||||
|
|
|
@ -46,7 +46,6 @@ RUNTIME_DEPS = [
|
|||
"@npm//dedent",
|
||||
"@npm//del",
|
||||
"@npm//execa",
|
||||
"@npm//jest-diff",
|
||||
"@npm//json-stable-stringify",
|
||||
"@npm//js-yaml",
|
||||
"@npm//lmdb-store",
|
||||
|
@ -76,7 +75,6 @@ TYPES_DEPS = [
|
|||
"@npm//cpy",
|
||||
"@npm//del",
|
||||
"@npm//execa",
|
||||
"@npm//jest-diff",
|
||||
"@npm//lmdb-store",
|
||||
"@npm//pirates",
|
||||
"@npm//rxjs",
|
||||
|
|
|
@ -8,11 +8,10 @@
|
|||
|
||||
import Path from 'path';
|
||||
|
||||
import jestDiff from 'jest-diff';
|
||||
import { REPO_ROOT } from '@kbn/utils';
|
||||
import { createAbsolutePathSerializer } from '@kbn/dev-utils';
|
||||
|
||||
import { reformatJestDiff, getOptimizerCacheKey, diffCacheKey } from './cache_keys';
|
||||
import { getOptimizerCacheKey } from './cache_keys';
|
||||
import { OptimizerConfig } from './optimizer_config';
|
||||
|
||||
jest.mock('./get_changes.ts', () => ({
|
||||
|
@ -101,98 +100,3 @@ describe('getOptimizerCacheKey()', () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('diffCacheKey()', () => {
|
||||
it('returns undefined if values are equal', () => {
|
||||
expect(diffCacheKey('1', '1')).toBe(undefined);
|
||||
expect(diffCacheKey(1, 1)).toBe(undefined);
|
||||
expect(diffCacheKey(['1', '2', { a: 'b' }], ['1', '2', { a: 'b' }])).toBe(undefined);
|
||||
expect(
|
||||
diffCacheKey(
|
||||
{
|
||||
a: '1',
|
||||
b: '2',
|
||||
},
|
||||
{
|
||||
b: '2',
|
||||
a: '1',
|
||||
}
|
||||
)
|
||||
).toBe(undefined);
|
||||
});
|
||||
|
||||
it('returns a diff if the values are different', () => {
|
||||
expect(diffCacheKey(['1', '2', { a: 'b' }], ['1', '2', { b: 'a' }])).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m [[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"2\\",[22m
|
||||
[2m {[22m
|
||||
[32m- \\"a\\": \\"b\\"[39m
|
||||
[31m+ \\"b\\": \\"a\\"[39m
|
||||
[2m }[22m
|
||||
[2m ][22m"
|
||||
`);
|
||||
expect(
|
||||
diffCacheKey(
|
||||
{
|
||||
a: '1',
|
||||
b: '1',
|
||||
},
|
||||
{
|
||||
b: '2',
|
||||
a: '2',
|
||||
}
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m {[22m
|
||||
[32m- \\"a\\": \\"1\\",[39m
|
||||
[32m- \\"b\\": \\"1\\"[39m
|
||||
[31m+ \\"a\\": \\"2\\",[39m
|
||||
[31m+ \\"b\\": \\"2\\"[39m
|
||||
[2m }[22m"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reformatJestDiff()', () => {
|
||||
it('reformats large jestDiff output to focus on the changed lines', () => {
|
||||
const diff = jestDiff(
|
||||
{
|
||||
a: ['1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', '1', '1', '1', '1', '1', '1'],
|
||||
},
|
||||
{
|
||||
b: ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '1', '1', '1', '1'],
|
||||
}
|
||||
);
|
||||
|
||||
expect(reformatJestDiff(diff)).toMatchInlineSnapshot(`
|
||||
"[32m- Expected[39m
|
||||
[31m+ Received[39m
|
||||
|
||||
[2m Object {[22m
|
||||
[32m- \\"a\\": Array [[39m
|
||||
[31m+ \\"b\\": Array [[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[32m- \\"2\\",[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[31m+ \\"2\\",[39m
|
||||
[2m \\"1\\",[22m
|
||||
[2m \\"1\\",[22m
|
||||
[2m ...[22m"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,12 +9,10 @@
|
|||
import Path from 'path';
|
||||
import Fs from 'fs';
|
||||
|
||||
import Chalk from 'chalk';
|
||||
import execa from 'execa';
|
||||
import { REPO_ROOT } from '@kbn/utils';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
import { diffStrings } from '@kbn/dev-utils';
|
||||
|
||||
import jestDiff from 'jest-diff';
|
||||
import jsonStable from 'json-stable-stringify';
|
||||
import { ascending, CacheableWorkerConfig } from '../common';
|
||||
|
||||
|
@ -36,78 +34,7 @@ export function diffCacheKey(expected?: unknown, actual?: unknown) {
|
|||
return;
|
||||
}
|
||||
|
||||
return reformatJestDiff(jestDiff(expectedJson, actualJson));
|
||||
}
|
||||
|
||||
export function reformatJestDiff(diff: string | null) {
|
||||
const diffLines = diff?.split('\n') || [];
|
||||
|
||||
if (
|
||||
diffLines.length < 4 ||
|
||||
stripAnsi(diffLines[0]) !== '- Expected' ||
|
||||
stripAnsi(diffLines[1]) !== '+ Received'
|
||||
) {
|
||||
throw new Error(`unexpected diff format: ${diff}`);
|
||||
}
|
||||
|
||||
const outputLines = [diffLines.shift(), diffLines.shift(), diffLines.shift()];
|
||||
|
||||
/**
|
||||
* buffer which contains between 0 and 5 lines from the diff which aren't additions or
|
||||
* deletions. The first three are the first three lines seen since the buffer was cleared
|
||||
* and the last two lines are the last two lines seen.
|
||||
*
|
||||
* When flushContext() is called we write the first two lines to output, an elipses if there
|
||||
* are five lines, and then the last two lines.
|
||||
*
|
||||
* At the very end we will write the last two lines of context if they're defined
|
||||
*/
|
||||
const contextBuffer: string[] = [];
|
||||
|
||||
/**
|
||||
* Convert a line to an empty line with elipses placed where the text on that line starts
|
||||
*/
|
||||
const toElipses = (line: string) => {
|
||||
return stripAnsi(line).replace(/^(\s*).*/, '$1...');
|
||||
};
|
||||
|
||||
while (diffLines.length) {
|
||||
const line = diffLines.shift()!;
|
||||
const plainLine = stripAnsi(line);
|
||||
if (plainLine.startsWith('+ ') || plainLine.startsWith('- ')) {
|
||||
// write contextBuffer to the outputLines
|
||||
if (contextBuffer.length) {
|
||||
outputLines.push(
|
||||
...contextBuffer.slice(0, 2),
|
||||
...(contextBuffer.length === 5
|
||||
? [Chalk.dim(toElipses(contextBuffer[2])), ...contextBuffer.slice(3, 5)]
|
||||
: contextBuffer.slice(2, 4))
|
||||
);
|
||||
|
||||
contextBuffer.length = 0;
|
||||
}
|
||||
|
||||
// add this line to the outputLines
|
||||
outputLines.push(line);
|
||||
} else {
|
||||
// update the contextBuffer with this line which doesn't represent a change
|
||||
if (contextBuffer.length === 5) {
|
||||
contextBuffer[3] = contextBuffer[4];
|
||||
contextBuffer[4] = line;
|
||||
} else {
|
||||
contextBuffer.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contextBuffer.length) {
|
||||
outputLines.push(
|
||||
...contextBuffer.slice(0, 2),
|
||||
...(contextBuffer.length > 2 ? [Chalk.dim(toElipses(contextBuffer[2]))] : [])
|
||||
);
|
||||
}
|
||||
|
||||
return outputLines.join('\n');
|
||||
return diffStrings(expectedJson, actualJson);
|
||||
}
|
||||
|
||||
export interface OptimizerCacheKey {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue