Skip to content

Instantly share code, notes, and snippets.

@nojvek
Last active May 19, 2017 08:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nojvek/f91dbd8b850d74f442841ff4ef743be7 to your computer and use it in GitHub Desktop.
Save nojvek/f91dbd8b850d74f442841ff4ef743be7 to your computer and use it in GitHub Desktop.
printDiff
printDiff(expected, encoded_actual, referencePath(relativeFileName), actualFileName);
/**
* Prints a nice diff that is useful for debugging baseline failures
* It doesn't print the most optimum diff but does it in O(n) time and gives a `good enough` diff for humans
* It also emits a `cp tests/baselines/local/<file> tests/baselines/reference/<file>`
* Which makes experience of updating basefiles case by case much more bearable
*/
export function printDiff(expectedText: string, actualText: string, expectedFileName: string, actualFileName: string) {
type LineNumMap = { [line: string]: number[] };
function getLineNumMap(lines: string[]): LineNumMap {
const lineNumMap: LineNumMap = Object.create(null);
for (let i = 0, len = lines.length; i < len; ++i) {
const line = lines[i];
if (!lineNumMap[line]) {
lineNumMap[line] = []
}
lineNumMap[line].push(i);
}
return lineNumMap;
}
function nextMatchingOffset(lineToMatch: string, curIndex: number, numLines: number, lineNumMap: LineNumMap): number {
if (lineNumMap[lineToMatch]) {
const lineNums = lineNumMap[lineToMatch];
for (let lineNum of lineNums) {
if (lineNum > curIndex) {
return (lineNum - curIndex);
}
}
}
return numLines - curIndex - 1;
}
const removedMarker = ` <-|`;
const addedMarker = ` ->|`;
const sameMarker = ` |`;
const expectedLines = expectedText.split(/\r?\n/g);
const actualLines = actualText.split(/\r?\n/g);
const numExpectedLines = expectedLines.length;
const numActualLines = actualLines.length;
const expectedLineMap = getLineNumMap(expectedLines);
const actualLineMap = getLineNumMap(actualLines);
console.log(`\ncp ${actualFileName} ${expectedFileName}`);
console.log(`${sameMarker} ${new Array(actualFileName.length).join('=')}`)
for (
let iActual = 0, iExpected = 0;
(iActual < numActualLines) && (iExpected < numExpectedLines);
) {
// Print lines that are the same
for (; actualLines[iActual] == expectedLines[iExpected]; iExpected++, iActual++) {
console.log(`${sameMarker} ${expectedLines[iExpected]}`);
}
// Get index of next matching line
const actualMatchingOffset = nextMatchingOffset(expectedLines[iExpected], iActual, numActualLines, actualLineMap);
const expectedMatchingOffset = nextMatchingOffset(actualLines[iActual], iExpected, numExpectedLines, expectedLineMap);
actualMatchingOffset + expectedMatchingOffset;
// if (expectedMatchingOffset <= actualMatchingOffset) {
// console.log(`${removedMarker} ${expectedLines[iExpected]}`);
// iExpected++;
// }
// else if (actualMatchingOffset < expectedMatchingOffset) {
// console.log(`${addedMarker} ${actualLines[iActual]}`);
// iActual++;
// }
// Print removed lines
for (; iExpected < numExpectedLines; iExpected++) {
console.log(`${removedMarker} ${expectedLines[iExpected]}`);
}
// print added lines
for (; iActual < numActualLines; iActual++) {
console.log(`${addedMarker} ${actualLines[iActual]}`);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment