UNPKG

fast-check

Version:

Property based testing framework for JavaScript (like QuickCheck)

92 lines (91 loc) 4.29 kB
import { bigInt } from '../bigInt.js'; import { Arbitrary } from '../../check/arbitrary/definition/Arbitrary.js'; import { Value } from '../../check/arbitrary/definition/Value.js'; import { makeLazy } from '../../stream/LazyIterableIterator.js'; import { applyFlagsOnChars, computeFlagsFromChars, computeNextFlags, computeTogglePositions, } from './helpers/ToggleFlags.js'; import { safeJoin, safeSlice } from '../../utils/globals.js'; import { BigInt } from '../../utils/globals.js'; export class MixedCaseArbitrary extends Arbitrary { constructor(stringArb, toggleCase, untoggleAll) { super(); this.stringArb = stringArb; this.toggleCase = toggleCase; this.untoggleAll = untoggleAll; } buildContextFor(rawStringValue, flagsValue) { return { rawString: rawStringValue.value, rawStringContext: rawStringValue.context, flags: flagsValue.value, flagsContext: flagsValue.context, }; } generate(mrng, biasFactor) { const rawStringValue = this.stringArb.generate(mrng, biasFactor); const chars = [...rawStringValue.value]; const togglePositions = computeTogglePositions(chars, this.toggleCase); const flagsArb = bigInt(BigInt(0), (BigInt(1) << BigInt(togglePositions.length)) - BigInt(1)); const flagsValue = flagsArb.generate(mrng, undefined); applyFlagsOnChars(chars, flagsValue.value, togglePositions, this.toggleCase); return new Value(safeJoin(chars, ''), this.buildContextFor(rawStringValue, flagsValue)); } canShrinkWithoutContext(value) { if (typeof value !== 'string') { return false; } return this.untoggleAll !== undefined ? this.stringArb.canShrinkWithoutContext(this.untoggleAll(value)) : this.stringArb.canShrinkWithoutContext(value); } shrink(value, context) { let contextSafe; if (context !== undefined) { contextSafe = context; } else { if (this.untoggleAll !== undefined) { const untoggledValue = this.untoggleAll(value); const valueChars = [...value]; const untoggledValueChars = [...untoggledValue]; const togglePositions = computeTogglePositions(untoggledValueChars, this.toggleCase); contextSafe = { rawString: untoggledValue, rawStringContext: undefined, flags: computeFlagsFromChars(untoggledValueChars, valueChars, togglePositions), flagsContext: undefined, }; } else { contextSafe = { rawString: value, rawStringContext: undefined, flags: BigInt(0), flagsContext: undefined, }; } } const rawString = contextSafe.rawString; const flags = contextSafe.flags; return this.stringArb .shrink(rawString, contextSafe.rawStringContext) .map((nRawStringValue) => { const nChars = [...nRawStringValue.value]; const nTogglePositions = computeTogglePositions(nChars, this.toggleCase); const nFlags = computeNextFlags(flags, nTogglePositions.length); applyFlagsOnChars(nChars, nFlags, nTogglePositions, this.toggleCase); return new Value(safeJoin(nChars, ''), this.buildContextFor(nRawStringValue, new Value(nFlags, undefined))); }) .join(makeLazy(() => { const chars = [...rawString]; const togglePositions = computeTogglePositions(chars, this.toggleCase); return bigInt(BigInt(0), (BigInt(1) << BigInt(togglePositions.length)) - BigInt(1)) .shrink(flags, contextSafe.flagsContext) .map((nFlagsValue) => { const nChars = safeSlice(chars); applyFlagsOnChars(nChars, nFlagsValue.value, togglePositions, this.toggleCase); return new Value(safeJoin(nChars, ''), this.buildContextFor(new Value(rawString, contextSafe.rawStringContext), nFlagsValue)); }); })); } }