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 ) : StringDiff { const convertedStringDiff = 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 , expected ) : 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 } ;