misc-utils-of-mine-generic
Version:
Miscellaneous utilities for JavaScript/TypeScript that I often use
84 lines (72 loc) • 2.88 kB
text/typescript
import { asArray } from './array'
type TextCompareMode = 'contains' | 'contained' | 'equals' | 'startsWith' | 'endsWith'
export type Multiplicity = 'anyOf' | 'allOf'
interface BaseCompareOptions {
negate?: boolean
}
export interface CompareTextOptions extends BaseCompareOptions {
caseInsensitive?: boolean
asCode?: boolean
verb?: TextCompareMode
}
interface CompareWithMultiplicityOptionsConcrete {
multiplicity?: Multiplicity
}
export interface CompareOptions extends CompareWithMultiplicityOptionsConcrete, BaseCompareOptions { }
export interface CompareTextsOptions extends CompareTextOptions, CompareWithMultiplicityOptionsConcrete { }
export function compareTexts(actual: string | string[], expected: string | string[], options: CompareTextsOptions) {
return compareWithMultiplicity(actual, expected, options, compareText)
}
export function compareText(actual: string, expected: string, options: CompareTextOptions) {
if (actual === expected) {
return options.negate ? negate(true) : true
}
actual = buildText(actual!, options)
expected = buildText(expected!, options)
if (!options.verb || options.verb === 'contains') {
return options.negate ? negate(actual.includes(expected)) : actual.includes(expected)
} else if (options.verb === 'equals') {
return options.negate ? negate(actual === expected) : actual === expected
} else if (options.verb === 'contained') {
return options.negate ? negate(expected.includes(actual)) : expected.includes(actual)
} else if (options.verb === 'endsWith') {
return options.negate ? negate(actual.endsWith(expected)) : actual.endsWith(expected)
} else if (options.verb === 'startsWith') {
return options.negate ? negate(actual.startsWith(expected)) : actual.startsWith(expected)
} else {
return options.negate ? negate(false) : false
}
}
function compareWithMultiplicity<T>(
_actual: T | T[],
_expected: T | T[],
options: CompareOptions,
predicate: (actual: T, expected: T, options: CompareOptions) => boolean
) {
const actual = asArray(_actual)
const expected = asArray(_expected)
if (actual === expected) {
return options.negate ? negate(true) : true
}
if (!options.multiplicity || options.multiplicity === 'anyOf') {
const r = !!actual.find(a => !!expected.find(e => predicate(a, e, options)))
return options.negate ? negate(r) : r
} else if (options.multiplicity === 'allOf') {
const r = !actual.find(a => !expected.find(e => predicate(a, e, options)))
return options.negate ? negate(r) : r
} else {
return options.negate ? negate(false) : false
}
}
function negate(b: boolean) {
return !b
}
function buildText(text: string, options: CompareTextOptions) {
if (options.caseInsensitive) {
text = text.toLowerCase()
}
if (options.asCode) {
text = text.replace(/\s+/g, ' ').trim()
}
return text
}