assertthat
Version:
assertthat provides fluent TDD.
120 lines (105 loc) • 3.88 kB
text/typescript
import { ArrayDiff } from '../../diffs/forArrays/ArrayDiff';
import { compareArrays } from '../forArrays/compareArrays';
import { intersperse } from '../../utils/intersperse';
import { InvalidOperation } from '../../errors';
import { maximumStringLengthForPreciseDiff } from '../../constants/maximumStringLengthForPreciveDiff';
import { unequalCharCost } from '../../constants/costs';
import {
AdditionDiffSegment as AdditionStringDiffSegment,
OmissionDiffSegment as OmissionStringDiffSegment
} from '../../diffs/forStrings/StringDiffSegment';
import { equalDiff, EqualDiff, isEqualDiff } from '../../diffs/EqualDiff';
import {
isAdditionDiffSegment as isAdditionArrayDiffSegment,
isChangeDiffSegment as isChangeArrayDiffSegment,
isEqualDiffSegment as isEqualArrayDiffSegment,
isOmissionDiffSegment as isOmissionArrayDiffSegment
} from '../../diffs/forArrays/ArrayDiffSegment';
import { isStringDiff, stringDiff, StringDiff } from '../../diffs/forStrings/StringDiff';
const convertArrayDiffToStringDiff = function (arrayDiff: ArrayDiff<string>): StringDiff {
const convertedStringDiff: StringDiff = stringDiff({
segments: [],
cost: 0
});
for (const arrayDiffSegment of arrayDiff.segments) {
if (isEqualArrayDiffSegment(arrayDiffSegment)) {
convertedStringDiff.segments.push({
equal: arrayDiffSegment.equal.join(''),
cost: arrayDiffSegment.cost
});
}
if (isChangeArrayDiffSegment(arrayDiffSegment)) {
const replaceSegment = {
replace: '',
replaceWith: '',
cost: 0
};
for (const change of arrayDiffSegment.change) {
if (!isStringDiff(change)) {
throw new InvalidOperation('Tried to convert ArrayDiff with sub-diff to StringDiff.');
}
replaceSegment.replace += (change.segments[0] as AdditionStringDiffSegment).addition;
replaceSegment.replaceWith += (change.segments[1] as OmissionStringDiffSegment).omission;
replaceSegment.cost += change.cost;
}
convertedStringDiff.segments.push(replaceSegment);
}
if (isOmissionArrayDiffSegment(arrayDiffSegment)) {
convertedStringDiff.segments.push({
omission: arrayDiffSegment.omission.join(''),
cost: arrayDiffSegment.cost
});
}
if (isAdditionArrayDiffSegment(arrayDiffSegment)) {
convertedStringDiff.segments.push({
addition: arrayDiffSegment.addition.join(''),
cost: arrayDiffSegment.cost
});
}
convertedStringDiff.cost += arrayDiffSegment.cost;
}
return convertedStringDiff;
};
const compareStrings = function (
actual: string,
expected: string
): StringDiff | EqualDiff {
if (actual === expected) {
return equalDiff({
value: actual
});
}
let actualExploded = [ ...actual ];
if (actualExploded.length > maximumStringLengthForPreciseDiff) {
actualExploded = intersperse(actual.split(' '), ' ');
}
if (actualExploded.length > maximumStringLengthForPreciseDiff) {
actualExploded = intersperse(actual.split('\n'), '\n');
}
let expectedExploded = [ ...expected ];
if (expectedExploded.length > maximumStringLengthForPreciseDiff) {
expectedExploded = intersperse(expected.split(' '), ' ');
}
if (expectedExploded.length > maximumStringLengthForPreciseDiff) {
expectedExploded = intersperse(expected.split('\n'), '\n');
}
if (actualExploded.length <= 1 && expectedExploded.length <= 1) {
return stringDiff({
segments: [
{ addition: actual, cost: unequalCharCost / 2 },
{ omission: expected, cost: unequalCharCost / 2 }
],
cost: unequalCharCost
});
}
const result = compareArrays(actualExploded, expectedExploded);
if (isEqualDiff(result)) {
return equalDiff({
value: actual
});
}
return convertArrayDiffToStringDiff(result);
};
export {
compareStrings
};