Best JavaScript code snippet using fast-check-monorepo
ArrayArbitrary.spec.ts
Source:ArrayArbitrary.spec.ts
1import fc from 'fast-check';2import prand from 'pure-rand';3import { ArrayArbitrary } from '../../../../src/arbitrary/_internals/ArrayArbitrary';4import { Value } from '../../../../src/check/arbitrary/definition/Value';5import { MaxLengthUpperBound } from '../../../../src/arbitrary/_internals/helpers/MaxLengthFromMinLength';6import { CustomSet } from '../../../../src/arbitrary/_internals/interfaces/CustomSet';7import { Stream } from '../../../../src/stream/Stream';8import { cloneMethod, hasCloneMethod } from '../../../../src/check/symbols';9import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary';10import { Random } from '../../../../src/random/generator/Random';11import * as IntegerMock from '../../../../src/arbitrary/integer';12import { fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers';13import { fakeRandom } from '../__test-helpers__/RandomHelpers';14import { buildShrinkTree, walkTree } from '../__test-helpers__/ShrinkTree';15import * as DepthContextMock from '../../../../src/arbitrary/_internals/helpers/DepthContext';16function beforeEachHook() {17 jest.resetModules();18 jest.restoreAllMocks();19 fc.configureGlobal({ beforeEach: beforeEachHook });20}21beforeEach(beforeEachHook);22describe('ArrayArbitrary', () => {23 describe('generate', () => {24 it('should concat all the generated values together when no set constraints ', () => {25 fc.assert(26 fc.property(27 fc.array(fc.tuple(fc.anything(), fc.anything())),28 fc.nat(),29 fc.nat(MaxLengthUpperBound),30 fc.nat(MaxLengthUpperBound),31 fc.anything(),32 (generatedValues, seed, aLength, bLength, integerContext) => {33 // Arrange34 const { acceptedValues, instance, generate } = prepareSetBuilderData(generatedValues, false);35 const { minLength, maxGeneratedLength, maxLength } = extractLengths(seed, aLength, bLength, acceptedValues);36 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();37 generateInteger.mockReturnValue(new Value(acceptedValues.size, integerContext));38 const integer = jest.spyOn(IntegerMock, 'integer');39 integer.mockReturnValue(integerInstance);40 const { instance: mrng } = fakeRandom();41 // Act42 const arb = new ArrayArbitrary(43 instance,44 minLength,45 maxGeneratedLength,46 maxLength,47 undefined,48 undefined,49 []50 );51 const g = arb.generate(mrng, undefined);52 // Assert53 expect(g.hasToBeCloned).toBe(false);54 expect(g.value).toEqual([...acceptedValues].map((v) => v.value));55 expect(integer).toHaveBeenCalledTimes(1);56 expect(integer).toHaveBeenCalledWith({ min: minLength, max: maxGeneratedLength });57 expect(generateInteger).toHaveBeenCalledTimes(1);58 expect(generateInteger).toHaveBeenCalledWith(mrng, undefined);59 expect(generate).toHaveBeenCalledTimes(acceptedValues.size);60 for (const call of generate.mock.calls) {61 expect(call).toEqual([mrng, undefined]);62 }63 }64 )65 );66 });67 it("should not concat all the values together in case they don't follow set contraints", () => {68 fc.assert(69 fc.property(70 fc.array(fc.tuple(fc.anything(), fc.anything(), fc.boolean())),71 fc.nat(),72 fc.nat(MaxLengthUpperBound),73 fc.nat(MaxLengthUpperBound),74 fc.anything(),75 (generatedValues, seed, aLength, bLength, integerContext) => {76 // Arrange77 const { acceptedValues, instance, generate, setBuilder } = prepareSetBuilderData(generatedValues, false);78 const { minLength, maxGeneratedLength, maxLength } = extractLengths(seed, aLength, bLength, acceptedValues);79 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();80 generateInteger.mockReturnValue(new Value(acceptedValues.size, integerContext));81 const integer = jest.spyOn(IntegerMock, 'integer');82 integer.mockReturnValue(integerInstance);83 const { instance: mrng } = fakeRandom();84 // Act85 const arb = new ArrayArbitrary(86 instance,87 minLength,88 maxGeneratedLength,89 maxLength,90 undefined,91 setBuilder,92 []93 );94 const g = arb.generate(mrng, undefined);95 // Assert96 expect(g.hasToBeCloned).toBe(false);97 // In the case of set the generated value might be smaller98 // The generator is allowed to stop whenever it considers at already tried to many times (maxGeneratedLength times)99 expect(g.value).toEqual([...acceptedValues].map((v) => v.value).slice(0, g.value.length));100 expect(integer).toHaveBeenCalledTimes(1);101 expect(integer).toHaveBeenCalledWith({ min: minLength, max: maxGeneratedLength });102 expect(generateInteger).toHaveBeenCalledTimes(1);103 expect(generateInteger).toHaveBeenCalledWith(mrng, undefined);104 expect(setBuilder).toHaveBeenCalledTimes(1);105 for (const call of generate.mock.calls) {106 expect(call).toEqual([mrng, undefined]);107 }108 }109 )110 );111 });112 it("should always pass bias to values' arbitrary when minLength equals maxGeneratedLength", () => {113 fc.assert(114 fc.property(115 fc.array(fc.tuple(fc.anything(), fc.anything(), fc.boolean())),116 fc.nat(),117 fc.nat(MaxLengthUpperBound),118 fc.anything(),119 fc.integer({ min: 2 }),120 fc.boolean(),121 (generatedValues, seed, aLength, integerContext, biasFactor, withSetBuilder) => {122 // Arrange123 const { acceptedValues, instance, setBuilder, generate } = prepareSetBuilderData(124 generatedValues,125 !withSetBuilder126 );127 const { minLength, maxLength } = extractLengths(seed, aLength, aLength, acceptedValues);128 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();129 generateInteger.mockReturnValue(new Value(minLength, integerContext));130 const integer = jest.spyOn(IntegerMock, 'integer');131 integer.mockReturnValue(integerInstance);132 const { instance: mrng } = fakeRandom();133 // Act134 const arb = new ArrayArbitrary(135 instance,136 minLength,137 minLength,138 maxLength,139 undefined,140 withSetBuilder ? setBuilder : undefined,141 []142 );143 const g = arb.generate(mrng, biasFactor);144 // Assert145 expect(g.hasToBeCloned).toBe(false);146 if (!withSetBuilder) {147 // In the case of set the generated value might be smaller148 // The generator is allowed to stop whenever it considers at already tried to many times (maxGeneratedLength times)149 expect(g.value).toEqual([...acceptedValues].map((v) => v.value).slice(0, minLength));150 } else {151 expect(g.value).toEqual(152 [...acceptedValues].map((v) => v.value).slice(0, Math.min(g.value.length, minLength))153 );154 }155 expect(integer).toHaveBeenCalledTimes(1);156 expect(integer).toHaveBeenCalledWith({ min: minLength, max: minLength });157 expect(generateInteger).toHaveBeenCalledTimes(1);158 expect(generateInteger).toHaveBeenCalledWith(mrng, undefined); // no need to bias it159 expect(setBuilder).toHaveBeenCalledTimes(withSetBuilder ? 1 : 0);160 expect(generate.mock.calls.length).toBeGreaterThanOrEqual(minLength);161 for (const call of generate.mock.calls) {162 expect(call).toEqual([mrng, biasFactor]); // but bias all sub-values163 }164 }165 )166 );167 });168 it('should bias depth the same way for any child and reset it at the end', () => {169 fc.assert(170 fc.property(171 fc.array(fc.tuple(fc.anything(), fc.anything(), fc.boolean())),172 fc.nat(),173 fc.nat(MaxLengthUpperBound),174 fc.nat(MaxLengthUpperBound),175 fc.anything(),176 fc.integer({ min: 2 }),177 fc.boolean(),178 (generatedValues, seed, aLength, bLength, integerContext, biasFactor, withSetBuilder) => {179 // Arrange180 const getDepthContextFor = jest.spyOn(DepthContextMock, 'getDepthContextFor');181 const depthContext = { depth: 0 };182 getDepthContextFor.mockReturnValue(depthContext);183 const seenDepths = new Set<number>();184 const { acceptedValues, instance, generate, setBuilder } = prepareSetBuilderData(185 generatedValues,186 !withSetBuilder,187 () => {188 seenDepths.add(depthContext.depth);189 }190 );191 const { minLength, maxGeneratedLength, maxLength } = extractLengths(seed, aLength, bLength, acceptedValues);192 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();193 generateInteger.mockReturnValue(new Value(minLength, integerContext));194 const integer = jest.spyOn(IntegerMock, 'integer');195 integer.mockReturnValue(integerInstance);196 const { instance: mrng } = fakeRandom();197 // Act198 const arb = new ArrayArbitrary(199 instance,200 minLength,201 maxGeneratedLength,202 maxLength,203 undefined,204 withSetBuilder ? setBuilder : undefined,205 []206 );207 arb.generate(mrng, biasFactor);208 // Assert209 expect(getDepthContextFor).toHaveBeenCalledTimes(1); // only array calls it in the test210 expect(depthContext.depth).toBe(0); // properly reset211 if (generate.mock.calls.length !== 0) {212 expect([...seenDepths]).toHaveLength(1); // always called with same depth213 } else {214 expect([...seenDepths]).toHaveLength(0); // never called on items215 }216 }217 )218 );219 });220 it('should produce a cloneable instance if provided one cloneable underlying', () => {221 // Arrange222 const { instance, generate } = fakeArbitrary<string[]>();223 generate224 .mockReturnValueOnce(new Value(['a'], undefined))225 .mockReturnValueOnce(new Value(Object.defineProperty(['b'], cloneMethod, { value: jest.fn() }), undefined))226 .mockReturnValueOnce(new Value(['c'], undefined))227 .mockReturnValueOnce(new Value(['d'], undefined));228 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();229 generateInteger.mockReturnValue(new Value(4, undefined));230 const integer = jest.spyOn(IntegerMock, 'integer');231 integer.mockReturnValue(integerInstance);232 const { instance: mrng } = fakeRandom();233 // Act234 const arb = new ArrayArbitrary(instance, 0, 10, 100, undefined, undefined, []);235 const g = arb.generate(mrng, undefined);236 // Assert237 expect(g.hasToBeCloned).toBe(true);238 expect(hasCloneMethod(g.value)).toBe(true);239 expect(g.value_).not.toEqual([['a'], ['b'], ['c'], ['d']]); // 2nd item is not just ['b']240 expect(g.value_.map((v) => [...v])).toEqual([['a'], ['b'], ['c'], ['d']]);241 });242 it('should not clone cloneable on generate', () => {243 // Arrange244 const cloneMethodImpl = jest.fn();245 const { instance, generate } = fakeArbitrary<string[]>();246 generate247 .mockReturnValueOnce(new Value(['a'], undefined))248 .mockReturnValueOnce(249 new Value(Object.defineProperty(['b'], cloneMethod, { value: cloneMethodImpl }), undefined)250 )251 .mockReturnValueOnce(new Value(['c'], undefined))252 .mockReturnValueOnce(new Value(['d'], undefined));253 const { instance: integerInstance, generate: generateInteger } = fakeArbitrary();254 generateInteger.mockReturnValue(new Value(4, undefined));255 const integer = jest.spyOn(IntegerMock, 'integer');256 integer.mockReturnValue(integerInstance);257 const { instance: mrng } = fakeRandom();258 // Act259 const arb = new ArrayArbitrary(instance, 0, 10, 100, undefined, undefined, []);260 const g = arb.generate(mrng, undefined);261 // Assert262 expect(cloneMethodImpl).not.toHaveBeenCalled();263 g.value; // not calling clone as this is the first access264 expect(cloneMethodImpl).not.toHaveBeenCalled();265 g.value; // calling clone as this is the second access266 expect(cloneMethodImpl).toHaveBeenCalledTimes(1);267 g.value; // calling clone (again) as this is the third access268 expect(cloneMethodImpl).toHaveBeenCalledTimes(2);269 g.value_; // not calling clone as we access value_ not value270 expect(cloneMethodImpl).toHaveBeenCalledTimes(2);271 });272 });273 describe('canShrinkWithoutContext', () => {274 it('should reject any array not matching the requirements on length', () => {275 fc.assert(276 fc.property(277 fc.array(fc.anything()),278 fc.boolean(),279 fc.nat(MaxLengthUpperBound),280 fc.nat(MaxLengthUpperBound),281 fc.nat(MaxLengthUpperBound),282 (value, withSetBuilder, aLength, bLength, cLength) => {283 // Arrange284 const [minLength, maxGeneratedLength, maxLength] = [aLength, bLength, cLength].sort((a, b) => a - b);285 fc.pre(value.length < minLength || value.length > maxLength);286 const { instance, canShrinkWithoutContext } = fakeArbitrary();287 const data: any[] = [];288 const customSet: CustomSet<Value<any>> = {289 size: () => data.length,290 getData: () => data,291 tryAdd: (vTest) => {292 data.push(vTest.value_);293 return true;294 },295 };296 const setBuilder = jest.fn();297 setBuilder.mockReturnValue(customSet);298 // Act299 const arb = new ArrayArbitrary(300 instance,301 minLength,302 maxGeneratedLength,303 maxLength,304 undefined,305 withSetBuilder ? setBuilder : undefined,306 []307 );308 const out = arb.canShrinkWithoutContext(value);309 // Assert310 expect(out).toBe(false);311 expect(canShrinkWithoutContext).not.toHaveBeenCalled();312 expect(setBuilder).not.toHaveBeenCalled();313 }314 )315 );316 });317 it('should reject any array with at least one entry rejected by the sub-arbitrary', () => {318 fc.assert(319 fc.property(320 fc.uniqueArray(fc.tuple(fc.anything(), fc.boolean()), {321 minLength: 1,322 selector: (v) => v[0],323 comparator: 'SameValue',324 }),325 fc.boolean(),326 fc.nat(MaxLengthUpperBound),327 fc.nat(MaxLengthUpperBound),328 fc.nat(MaxLengthUpperBound),329 (value, withSetBuilder, offsetMin, offsetMax, maxGeneratedLength) => {330 // Arrange331 fc.pre(value.some((v) => !v[1]));332 const minLength = Math.min(Math.max(0, value.length - offsetMin), maxGeneratedLength);333 const maxLength = Math.max(Math.min(MaxLengthUpperBound, value.length + offsetMax), maxGeneratedLength);334 const { instance, canShrinkWithoutContext } = fakeArbitrary();335 canShrinkWithoutContext.mockImplementation((vTest) => value.find((v) => Object.is(v[0], vTest))![1]);336 const data: any[] = [];337 const customSet: CustomSet<Value<any>> = {338 size: () => data.length,339 getData: () => data,340 tryAdd: (vTest) => {341 data.push(vTest.value_);342 return true;343 },344 };345 const setBuilder = jest.fn();346 setBuilder.mockReturnValue(customSet);347 // Act348 const arb = new ArrayArbitrary(349 instance,350 minLength,351 maxGeneratedLength,352 maxLength,353 undefined,354 withSetBuilder ? setBuilder : undefined,355 []356 );357 const out = arb.canShrinkWithoutContext(value.map((v) => v[0]));358 // Assert359 expect(out).toBe(false);360 expect(canShrinkWithoutContext).toHaveBeenCalled();361 }362 )363 );364 });365 it('should reject any array not matching requirements for set constraints', () => {366 fc.assert(367 fc.property(368 fc.uniqueArray(fc.tuple(fc.anything(), fc.boolean()), {369 minLength: 1,370 selector: (v) => v[0],371 comparator: 'SameValue',372 }),373 fc.nat(MaxLengthUpperBound),374 fc.nat(MaxLengthUpperBound),375 fc.nat(MaxLengthUpperBound),376 (value, offsetMin, offsetMax, maxGeneratedLength) => {377 // Arrange378 fc.pre(value.some((v) => !v[1]));379 const minLength = Math.min(Math.max(0, value.length - offsetMin), maxGeneratedLength);380 const maxLength = Math.max(Math.min(MaxLengthUpperBound, value.length + offsetMax), maxGeneratedLength);381 const { instance, canShrinkWithoutContext } = fakeArbitrary();382 canShrinkWithoutContext.mockReturnValue(true);383 const data: any[] = [];384 const customSet: CustomSet<Value<any>> = {385 size: () => data.length,386 getData: () => data,387 tryAdd: (vTest) => {388 if (value.find((v) => Object.is(v[0], vTest.value_))![1]) {389 data.push(vTest.value_);390 return true;391 }392 return false;393 },394 };395 const setBuilder = jest.fn();396 setBuilder.mockReturnValue(customSet);397 // Act398 const arb = new ArrayArbitrary(399 instance,400 minLength,401 maxGeneratedLength,402 maxLength,403 undefined,404 setBuilder,405 []406 );407 const out = arb.canShrinkWithoutContext(value.map((v) => v[0]));408 // Assert409 expect(out).toBe(false);410 expect(canShrinkWithoutContext).toHaveBeenCalled();411 expect(setBuilder).toHaveBeenCalled();412 }413 )414 );415 });416 it('should reject any sparse array', () => {417 fc.assert(418 fc.property(419 fc.sparseArray(fc.anything()),420 fc.boolean(),421 fc.nat(MaxLengthUpperBound),422 fc.nat(MaxLengthUpperBound),423 fc.nat(MaxLengthUpperBound),424 (value, withSetBuilder, offsetMin, offsetMax, maxGeneratedLength) => {425 // Arrange426 fc.pre(value.length !== Object.keys(value).length);427 const minLength = Math.min(Math.max(0, value.length - offsetMin), maxGeneratedLength);428 const maxLength = Math.max(Math.min(MaxLengthUpperBound, value.length + offsetMax), maxGeneratedLength);429 const { instance, canShrinkWithoutContext } = fakeArbitrary();430 canShrinkWithoutContext.mockReturnValue(true);431 const data: any[] = [];432 const customSet: CustomSet<Value<any>> = {433 size: () => data.length,434 getData: () => data,435 tryAdd: (vTest) => {436 data.push(vTest.value_);437 return true;438 },439 };440 const setBuilder = jest.fn();441 setBuilder.mockReturnValue(customSet);442 // Act443 const arb = new ArrayArbitrary(444 instance,445 minLength,446 maxGeneratedLength,447 maxLength,448 undefined,449 withSetBuilder ? setBuilder : undefined,450 []451 );452 const out = arb.canShrinkWithoutContext(value);453 // Assert454 expect(out).toBe(false);455 }456 )457 );458 });459 it('should accept all other arrays', () => {460 fc.assert(461 fc.property(462 fc.array(fc.anything()),463 fc.boolean(),464 fc.nat(MaxLengthUpperBound),465 fc.nat(MaxLengthUpperBound),466 fc.nat(MaxLengthUpperBound),467 (value, withSetBuilder, offsetMin, offsetMax, maxGeneratedLength) => {468 // Arrange469 const minLength = Math.min(Math.max(0, value.length - offsetMin), maxGeneratedLength);470 const maxLength = Math.max(Math.min(MaxLengthUpperBound, value.length + offsetMax), maxGeneratedLength);471 const { instance, canShrinkWithoutContext } = fakeArbitrary();472 canShrinkWithoutContext.mockReturnValue(true);473 const data: any[] = [];474 const customSet: CustomSet<Value<any>> = {475 size: () => data.length,476 getData: () => data,477 tryAdd: (vTest) => {478 data.push(vTest.value_);479 return true;480 },481 };482 const setBuilder = jest.fn();483 setBuilder.mockReturnValue(customSet);484 // Act485 const arb = new ArrayArbitrary(486 instance,487 minLength,488 maxGeneratedLength,489 maxLength,490 undefined,491 withSetBuilder ? setBuilder : undefined,492 []493 );494 const out = arb.canShrinkWithoutContext(value);495 // Assert496 expect(out).toBe(true);497 }498 )499 );500 });501 });502});503describe('ArrayArbitrary (integration)', () => {504 it('should not re-use twice the same instance of cloneable', () => {505 // Arrange506 const alreadySeenCloneable = new Set<unknown>();507 const mrng = new Random(prand.mersenne(0));508 const arb = new ArrayArbitrary(new CloneableArbitrary(), 0, 5, 100, undefined, undefined, []); // 0 to 5 generated items509 // Act510 let g = arb.generate(mrng, undefined);511 while (g.value.length !== 3) {512 // 3 allows to shrink something large enough but not too large513 // walking through the tree when >3 takes much longer514 g = arb.generate(mrng, undefined);515 }516 const treeA = buildShrinkTree(arb, g);517 const treeB = buildShrinkTree(arb, g);518 // Assert519 walkTree(treeA, (cloneable) => {520 expect(alreadySeenCloneable.has(cloneable)).toBe(false);521 alreadySeenCloneable.add(cloneable);522 for (const subCloneable of cloneable) {523 expect(alreadySeenCloneable.has(subCloneable)).toBe(false);524 alreadySeenCloneable.add(subCloneable);525 }526 });527 walkTree(treeB, (cloneable) => {528 expect(alreadySeenCloneable.has(cloneable)).toBe(false);529 alreadySeenCloneable.add(cloneable);530 for (const subCloneable of cloneable) {531 expect(alreadySeenCloneable.has(subCloneable)).toBe(false);532 alreadySeenCloneable.add(subCloneable);533 }534 });535 });536});537// Helpers538function prepareSetBuilderData(539 generatedValues: [value: any, context: any, rejected?: boolean][],540 acceptAll: boolean,541 onGenerateHook?: () => void542) {543 const acceptedValues = new Set<Value<any>>();544 const { instance, generate } = fakeArbitrary();545 for (const v of generatedValues) {546 const value = new Value(v[0], v[1]);547 const rejected = v[2];548 if (!rejected || acceptAll) {549 acceptedValues.add(value);550 }551 generate.mockImplementationOnce(() => {552 if (onGenerateHook !== undefined) {553 onGenerateHook();554 }555 return value;556 });557 }558 const data: any[] = [];559 const customSet: CustomSet<Value<any>> = {560 size: () => data.length,561 getData: () => data,562 tryAdd: (value) => {563 if (acceptedValues.has(value)) {564 data.push(value);565 return true;566 }567 return false;568 },569 };570 const setBuilder = jest.fn();571 setBuilder.mockReturnValue(customSet);572 return { acceptedValues, instance, generate, setBuilder };573}574function extractLengths(minLengthSeed: number, aLength: number, bLength: number, acceptedValues: Set<unknown>) {575 const minLength = minLengthSeed % (acceptedValues.size || 1);576 const [maxGeneratedLength, maxLength] = aLength < bLength ? [aLength, bLength] : [bLength, aLength];577 fc.pre(maxGeneratedLength >= acceptedValues.size);578 return { minLength, maxGeneratedLength, maxLength };579}580class CloneableArbitrary extends Arbitrary<number[]> {581 private instance() {582 return Object.defineProperty([], cloneMethod, { value: () => this.instance() });583 }584 generate(_mrng: Random): Value<number[]> {585 return new Value(this.instance(), { shrunkOnce: false });586 }587 canShrinkWithoutContext(_value: unknown): _value is number[] {588 throw new Error('No call expected in that scenario');589 }590 shrink(value: number[], context?: unknown): Stream<Value<number[]>> {591 if (typeof context !== 'object' || context === null || !('shrunkOnce' in context)) {592 throw new Error('Invalid context for CloneableArbitrary');593 }594 const safeContext = context as { shrunkOnce: boolean };595 if (safeContext.shrunkOnce) {596 return Stream.nil();597 }598 return Stream.of(new Value(this.instance(), { shrunkOnce: true }));599 }...
TupleArbitrary.spec.ts
Source:TupleArbitrary.spec.ts
1import { TupleArbitrary } from '../../../../src/arbitrary/_internals/TupleArbitrary';2import { Value } from '../../../../src/check/arbitrary/definition/Value';3import { FakeIntegerArbitrary, fakeArbitrary } from '../__test-helpers__/ArbitraryHelpers';4import { fakeRandom } from '../__test-helpers__/RandomHelpers';5import { cloneMethod, hasCloneMethod } from '../../../../src/check/symbols';6import { Stream } from '../../../../src/stream/Stream';7import {8 assertProduceValuesShrinkableWithoutContext,9 assertProduceCorrectValues,10 assertShrinkProducesSameValueWithoutInitialContext,11 assertShrinkProducesStrictlySmallerValue,12 assertProduceSameValueGivenSameSeed,13} from '../__test-helpers__/ArbitraryAssertions';14import { buildShrinkTree, renderTree, walkTree } from '../__test-helpers__/ShrinkTree';15import { Arbitrary } from '../../../../src/check/arbitrary/definition/Arbitrary';16import { Random } from '../../../../src/random/generator/Random';17describe('TupleArbitrary', () => {18 describe('generate', () => {19 it('should merge results coming from underlyings and call them with the exact same inputs as the received ones', () => {20 // Arrange21 const expectedBiasFactor = 48;22 const vA = Symbol();23 const vB = Symbol();24 const vC = Symbol();25 const { instance: instanceA, generate: generateA } = fakeArbitrary<symbol>();26 const { instance: instanceB, generate: generateB } = fakeArbitrary<symbol>();27 const { instance: instanceC, generate: generateC } = fakeArbitrary<symbol>();28 generateA.mockReturnValueOnce(new Value(vA, undefined));29 generateB.mockReturnValueOnce(new Value(vB, undefined));30 generateC.mockReturnValueOnce(new Value(vC, undefined));31 const { instance: mrng } = fakeRandom();32 // Act33 const arb = new TupleArbitrary([instanceA, instanceB, instanceC]);34 const g = arb.generate(mrng, expectedBiasFactor);35 // Assert36 expect(g.value).toEqual([vA, vB, vC]);37 expect(generateA).toHaveBeenCalledWith(mrng, expectedBiasFactor);38 expect(generateB).toHaveBeenCalledWith(mrng, expectedBiasFactor);39 expect(generateC).toHaveBeenCalledWith(mrng, expectedBiasFactor);40 });41 it('should produce a cloneable instance if provided one cloneable underlying', () => {42 // Arrange43 const { instance: fakeArbitraryNotCloneableA, generate: generateA } = fakeArbitrary<string[]>();44 const { instance: fakeArbitraryCloneableB, generate: generateB } = fakeArbitrary<string[]>();45 generateA.mockReturnValue(new Value([], undefined));46 generateB.mockReturnValue(new Value(Object.defineProperty([], cloneMethod, { value: jest.fn() }), undefined));47 const { instance: mrng } = fakeRandom();48 // Act49 const arb = new TupleArbitrary([fakeArbitraryNotCloneableA, fakeArbitraryCloneableB]);50 const g = arb.generate(mrng, undefined);51 // Assert52 expect(g.hasToBeCloned).toBe(true);53 expect(hasCloneMethod(g.value)).toBe(true);54 });55 it('should not produce a cloneable instance if no cloneable underlyings', () => {56 // Arrange57 const { instance: fakeArbitraryNotCloneableA, generate: generateA } = fakeArbitrary<string[]>();58 const { instance: fakeArbitraryNotCloneableB, generate: generateB } = fakeArbitrary<string[]>();59 generateA.mockReturnValue(new Value([], undefined));60 generateB.mockReturnValue(new Value([], undefined));61 const { instance: mrng } = fakeRandom();62 // Act63 const arb = new TupleArbitrary([fakeArbitraryNotCloneableA, fakeArbitraryNotCloneableB]);64 const g = arb.generate(mrng, undefined);65 // Assert66 expect(g.hasToBeCloned).toBe(false);67 expect(hasCloneMethod(g.value)).toBe(false);68 });69 it('should not clone cloneable on generate', () => {70 // Arrange71 const { instance: fakeArbitraryNotCloneableA, generate: generateA } = fakeArbitrary<string[]>();72 const { instance: fakeArbitraryCloneableB, generate: generateB } = fakeArbitrary<string[]>();73 const cloneMethodImpl = jest.fn();74 generateA.mockReturnValue(new Value([], undefined));75 generateB.mockReturnValue(76 new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined)77 );78 const { instance: mrng } = fakeRandom();79 // Act80 const arb = new TupleArbitrary([fakeArbitraryNotCloneableA, fakeArbitraryCloneableB]);81 arb.generate(mrng, undefined);82 // Assert83 expect(cloneMethodImpl).not.toHaveBeenCalled();84 });85 });86 describe('canShrinkWithoutContext', () => {87 it.each`88 canA | canB | canC89 ${false} | ${false} | ${false}90 ${false} | ${true} | ${true}91 ${true} | ${false} | ${true}92 ${true} | ${true} | ${false}93 ${true} | ${true} | ${true}94 `(95 'should merge results coming from underlyings for canShrinkWithoutContext if received array has the right size',96 ({ canA, canB, canC }) => {97 // Arrange98 const vA = Symbol();99 const vB = Symbol();100 const vC = Symbol();101 const { instance: instanceA, canShrinkWithoutContext: canShrinkWithoutContextA } = fakeArbitrary<symbol>();102 const { instance: instanceB, canShrinkWithoutContext: canShrinkWithoutContextB } = fakeArbitrary<symbol>();103 const { instance: instanceC, canShrinkWithoutContext: canShrinkWithoutContextC } = fakeArbitrary<symbol>();104 canShrinkWithoutContextA.mockReturnValueOnce(canA);105 canShrinkWithoutContextB.mockReturnValueOnce(canB);106 canShrinkWithoutContextC.mockReturnValueOnce(canC);107 // Act108 const arb = new TupleArbitrary([instanceA, instanceB, instanceC]);109 const out = arb.canShrinkWithoutContext([vA, vB, vC]);110 // Assert111 expect(out).toBe(canA && canB && canC);112 expect(canShrinkWithoutContextA).toHaveBeenCalledWith(vA);113 if (canA) expect(canShrinkWithoutContextB).toHaveBeenCalledWith(vB);114 else expect(canShrinkWithoutContextB).not.toHaveBeenCalled();115 if (canA && canB) expect(canShrinkWithoutContextC).toHaveBeenCalledWith(vC);116 else expect(canShrinkWithoutContextC).not.toHaveBeenCalled();117 }118 );119 it('should not call underlyings on canShrinkWithoutContext if size is invalid', () => {120 // Arrange121 const { instance: instanceA, canShrinkWithoutContext: canShrinkWithoutContextA } = fakeArbitrary<symbol>();122 const { instance: instanceB, canShrinkWithoutContext: canShrinkWithoutContextB } = fakeArbitrary<symbol>();123 const { instance: instanceC, canShrinkWithoutContext: canShrinkWithoutContextC } = fakeArbitrary<symbol>();124 // Act125 const arb = new TupleArbitrary([instanceA, instanceB, instanceC]);126 const out = arb.canShrinkWithoutContext([Symbol(), Symbol(), Symbol(), Symbol()]);127 // Assert128 expect(out).toBe(false);129 expect(canShrinkWithoutContextA).not.toHaveBeenCalled();130 expect(canShrinkWithoutContextB).not.toHaveBeenCalled();131 expect(canShrinkWithoutContextC).not.toHaveBeenCalled();132 });133 });134 describe('shrink', () => {135 it('should call back arbitraries on shrink with the initially returned contextq', () => {136 // Arrange137 const expectedBiasFactor = 48;138 const vA = Symbol();139 const vB = Symbol();140 const vC = Symbol();141 const contextA = Symbol();142 const contextB = Symbol();143 const contextC = Symbol();144 const { instance: instanceA, generate: generateA, shrink: shrinkA } = fakeArbitrary<symbol>();145 const { instance: instanceB, generate: generateB, shrink: shrinkB } = fakeArbitrary<symbol>();146 const { instance: instanceC, generate: generateC, shrink: shrinkC } = fakeArbitrary<symbol>();147 generateA.mockReturnValueOnce(new Value(vA, contextA));148 generateB.mockReturnValueOnce(new Value(vB, contextB));149 generateC.mockReturnValueOnce(new Value(vC, contextC));150 const shrinkA1 = Symbol();151 const shrinkA2 = Symbol();152 const shrinkB1 = Symbol();153 const shrinkC1 = Symbol();154 const shrinkC2 = Symbol();155 const shrinkC3 = Symbol();156 shrinkA.mockReturnValueOnce(Stream.of(new Value(shrinkA1 as symbol, undefined), new Value(shrinkA2, undefined)));157 shrinkB.mockReturnValueOnce(Stream.of(new Value(shrinkB1 as symbol, undefined)));158 shrinkC.mockReturnValueOnce(159 Stream.of(160 new Value(shrinkC1 as symbol, undefined),161 new Value(shrinkC2, undefined),162 new Value(shrinkC3, undefined)163 )164 );165 const { instance: mrng } = fakeRandom();166 // Act167 const arb = new TupleArbitrary([instanceA, instanceB, instanceC]);168 const g = arb.generate(mrng, expectedBiasFactor);169 const shrinks = [...arb.shrink(g.value, g.context)];170 // Assert171 expect(shrinks).toHaveLength(2 /* A */ + 1 /* B */ + 3 /* C */);172 expect(shrinks.map((v) => v.value)).toEqual([173 [shrinkA1, vB, vC],174 [shrinkA2, vB, vC],175 [vA, shrinkB1, vC],176 [vA, vB, shrinkC1],177 [vA, vB, shrinkC2],178 [vA, vB, shrinkC3],179 ]);180 expect(shrinkA).toHaveBeenCalledWith(vA, contextA);181 expect(shrinkB).toHaveBeenCalledWith(vB, contextB);182 expect(shrinkC).toHaveBeenCalledWith(vC, contextC);183 });184 it('should clone cloneable on shrink', () => {185 // Arrange186 const { instance: fakeArbitraryNotCloneableA, generate: generateA, shrink: shrinkA } = fakeArbitrary<string[]>();187 const { instance: fakeArbitraryCloneableB, generate: generateB, shrink: shrinkB } = fakeArbitrary<string[]>();188 const { instance: fakeArbitraryNotCloneableC, generate: generateC, shrink: shrinkC } = fakeArbitrary<string[]>();189 const cloneMethodImpl = jest190 .fn()191 .mockImplementation(() => Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }));192 generateA.mockReturnValue(new Value([], undefined));193 shrinkA.mockReturnValue(Stream.of(new Value([], undefined), new Value([], undefined)));194 generateB.mockReturnValue(195 new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined)196 );197 shrinkB.mockReturnValue(198 Stream.of(199 new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined),200 new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined),201 new Value(Object.defineProperty([], cloneMethod, { value: cloneMethodImpl }), undefined)202 )203 );204 generateC.mockReturnValue(new Value([], undefined));205 shrinkC.mockReturnValue(206 Stream.of(207 new Value([], undefined),208 new Value([], undefined),209 new Value([], undefined),210 new Value([], undefined)211 )212 );213 const { instance: mrng } = fakeRandom();214 // Act215 const arb = new TupleArbitrary([fakeArbitraryNotCloneableA, fakeArbitraryCloneableB, fakeArbitraryNotCloneableC]);216 const g = arb.generate(mrng, undefined);217 expect(cloneMethodImpl).not.toHaveBeenCalled();218 const shrinkLazy = arb.shrink(g.value, g.context);219 expect(cloneMethodImpl).not.toHaveBeenCalled();220 const shrinks = [...shrinkLazy];221 // Assert222 expect(shrinks).toHaveLength(2 /* A */ + 3 /* B */ + 4 /* C */);223 expect(cloneMethodImpl).toHaveBeenCalledTimes(shrinks.length);224 });225 });226});227describe('TupleArbitrary (integration)', () => {228 const isCorrect = (value: number[]) => Array.isArray(value) && value.length === 3;229 const isStrictlySmaller = (t1: number[], t2: number[]) => t1.findIndex((v, idx) => v < t2[idx]) !== -1;230 const tupleBuilder = () =>231 new TupleArbitrary([new FakeIntegerArbitrary(), new FakeIntegerArbitrary(), new FakeIntegerArbitrary()]);232 it('should produce the same values given the same seed', () => {233 assertProduceSameValueGivenSameSeed(tupleBuilder);234 });235 it('should only produce correct values', () => {236 assertProduceCorrectValues(tupleBuilder, isCorrect);237 });238 it('should produce values seen as shrinkable without any context', () => {239 assertProduceValuesShrinkableWithoutContext(tupleBuilder);240 });241 it('should be able to shrink to the same values without initial context (if underlyings do)', () => {242 assertShrinkProducesSameValueWithoutInitialContext(tupleBuilder);243 });244 it('should preserve strictly smaller ordering in shrink (if underlyings do)', () => {245 assertShrinkProducesStrictlySmallerValue(tupleBuilder, isStrictlySmaller);246 });247 it('should produce the right shrinking tree', () => {248 // Arrange249 const arb = new TupleArbitrary([new FirstArbitrary(), new SecondArbitrary()]);250 const { instance: mrng } = fakeRandom();251 // Act252 const g = arb.generate(mrng, undefined);253 const renderedTree = renderTree(buildShrinkTree(arb, g)).join('\n');254 // Assert255 expect(g.hasToBeCloned).toBe(false);256 expect(g.value).toBe(g.value_);257 expect(g.value).toEqual([expectedFirst, expectedSecond]);258 expect(renderedTree).toMatchInlineSnapshot(`259 "[4,97]260 â> [2,97]261 | â> [0,97]262 | | â> [0,99]263 | | â> [0,98]264 | | â> [0,100]265 | â> [2,99]266 | | â> [0,99]267 | â> [2,98]268 | â> [0,98]269 | | â> [0,100]270 | â> [2,100]271 | â> [0,100]272 â> [3,97]273 | â> [0,97]274 | | â> [0,99]275 | | â> [0,98]276 | | â> [0,100]277 | â> [1,97]278 | | â> [1,99]279 | | â> [1,98]280 | | â> [1,100]281 | â> [3,99]282 | | â> [0,99]283 | | â> [1,99]284 | â> [3,98]285 | â> [0,98]286 | | â> [0,100]287 | â> [1,98]288 | | â> [1,100]289 | â> [3,100]290 | â> [0,100]291 | â> [1,100]292 â> [4,99]293 | â> [2,99]294 | | â> [0,99]295 | â> [3,99]296 | â> [0,99]297 | â> [1,99]298 â> [4,98]299 â> [2,98]300 | â> [0,98]301 | | â> [0,100]302 | â> [2,100]303 | â> [0,100]304 â> [3,98]305 | â> [0,98]306 | | â> [0,100]307 | â> [1,98]308 | | â> [1,100]309 | â> [3,100]310 | â> [0,100]311 | â> [1,100]312 â> [4,100]313 â> [2,100]314 | â> [0,100]315 â> [3,100]316 â> [0,100]317 â> [1,100]"318 `);319 });320 it('should not re-use twice the same instance of cloneable', () => {321 // Arrange322 const alreadySeenCloneable = new Set<unknown>();323 const arb = new TupleArbitrary([new FirstArbitrary(), new CloneableArbitrary(), new SecondArbitrary()]);324 const { instance: mrng } = fakeRandom();325 // Act326 const g = arb.generate(mrng, undefined);327 const treeA = buildShrinkTree(arb, g);328 const treeB = buildShrinkTree(arb, g);329 // Assert330 walkTree(treeA, ([_first, cloneable, _second]) => {331 expect(alreadySeenCloneable.has(cloneable)).toBe(false);332 alreadySeenCloneable.add(cloneable);333 });334 walkTree(treeB, ([_first, cloneable, _second]) => {335 expect(alreadySeenCloneable.has(cloneable)).toBe(false);336 alreadySeenCloneable.add(cloneable);337 });338 });339});340// Helpers341const expectedFirst = 4;342const expectedSecond = 97;343class FirstArbitrary extends Arbitrary<number> {344 generate(_mrng: Random): Value<number> {345 return new Value(expectedFirst, { step: 2 });346 }347 canShrinkWithoutContext(_value: unknown): _value is number {348 throw new Error('No call expected in that scenario');349 }350 shrink(value: number, context?: unknown): Stream<Value<number>> {351 if (typeof context !== 'object' || context === null || !('step' in context)) {352 throw new Error('Invalid context for FirstArbitrary');353 }354 if (value <= 0) {355 return Stream.nil();356 }357 const currentStep = (context as { step: number }).step;358 const nextStep = currentStep + 1;359 return Stream.of(360 ...(value - currentStep >= 0 ? [new Value(value - currentStep, { step: nextStep })] : []),361 ...(value - currentStep + 1 >= 0 ? [new Value(value - currentStep + 1, { step: nextStep })] : [])362 );363 }364}365class SecondArbitrary extends Arbitrary<number> {366 generate(_mrng: Random): Value<number> {367 return new Value(expectedSecond, { step: 2 });368 }369 canShrinkWithoutContext(_value: unknown): _value is number {370 throw new Error('No call expected in that scenario');371 }372 shrink(value: number, context?: unknown): Stream<Value<number>> {373 if (typeof context !== 'object' || context === null || !('step' in context)) {374 throw new Error('Invalid context for SecondArbitrary');375 }376 if (value >= 100) {377 return Stream.nil();378 }379 const currentStep = (context as { step: number }).step;380 const nextStep = currentStep + 1;381 return Stream.of(382 ...(value + currentStep <= 100 ? [new Value(value + currentStep, { step: nextStep })] : []),383 ...(value + currentStep - 1 <= 100 ? [new Value(value + currentStep - 1, { step: nextStep })] : [])384 );385 }386}387class CloneableArbitrary extends Arbitrary<number[]> {388 private instance() {389 return Object.defineProperty([], cloneMethod, { value: () => this.instance() });390 }391 generate(_mrng: Random): Value<number[]> {392 return new Value(this.instance(), { shrunkOnce: false });393 }394 canShrinkWithoutContext(_value: unknown): _value is number[] {395 throw new Error('No call expected in that scenario');396 }397 shrink(value: number[], context?: unknown): Stream<Value<number[]>> {398 if (typeof context !== 'object' || context === null || !('shrunkOnce' in context)) {399 throw new Error('Invalid context for CloneableArbitrary');400 }401 const safeContext = context as { shrunkOnce: boolean };402 if (safeContext.shrunkOnce) {403 return Stream.nil();404 }405 return Stream.of(new Value(this.instance(), { shrunkOnce: true }));406 }...
ConstantArbitrary.spec.ts
Source:ConstantArbitrary.spec.ts
1import fc from 'fast-check';2import { ConstantArbitrary } from '../../../../src/arbitrary/_internals/ConstantArbitrary';3import { fakeRandom } from '../__test-helpers__/RandomHelpers';4import { cloneMethod } from '../../../../src/check/symbols';5import {6 assertProduceValuesShrinkableWithoutContext,7 assertProduceCorrectValues,8 assertShrinkProducesStrictlySmallerValue,9 assertProduceSameValueGivenSameSeed,10} from '../__test-helpers__/ArbitraryAssertions';11import { buildShrinkTree, walkTree } from '../__test-helpers__/ShrinkTree';12describe('ConstantArbitrary', () => {13 describe('generate', () => {14 it('should never call Random when provided a single value', () => {15 // Arrange16 const expectedBiasFactor = 48;17 const value = Symbol();18 const { instance: mrng } = fakeRandom();19 // Act20 const arb = new ConstantArbitrary([value]);21 const g = arb.generate(mrng, expectedBiasFactor);22 // Assert23 expect(g.value).toEqual(value);24 expect(g.hasToBeCloned).toBe(false);25 });26 it('should call Random to generate any integer in [0, length-1] when provided multiple values', () =>27 fc.assert(28 fc.property(29 fc.array(fc.anything(), { minLength: 2 }),30 fc.option(fc.integer({ min: 2 }), { nil: undefined }),31 fc.nat(),32 (values, biasFactor, mod) => {33 // Arrange34 const { instance: mrng, nextInt } = fakeRandom();35 nextInt.mockImplementation((a, b) => a + (mod % (b - a + 1)));36 // Act37 const arb = new ConstantArbitrary(values);38 const g = arb.generate(mrng, biasFactor);39 // Assert40 expect(nextInt).toHaveBeenCalledTimes(1);41 expect(nextInt).toHaveBeenCalledWith(0, values.length - 1);42 expect(values).toContainEqual(g.value);43 }44 )45 ));46 it('should be able to generate any of the requested values', () =>47 fc.assert(48 fc.property(49 fc.array(fc.anything(), { minLength: 2 }),50 fc.option(fc.integer({ min: 2 }), { nil: undefined }),51 (values, biasFactor) => {52 // Arrange53 const { instance: mrng, nextInt } = fakeRandom();54 // Act / Assert55 const arb = new ConstantArbitrary(values);56 const notSeenValues = [...values];57 for (let idx = 0; idx !== values.length; ++idx) {58 nextInt.mockImplementationOnce((a, _b) => a + idx);59 const g = arb.generate(mrng, biasFactor);60 const index = notSeenValues.findIndex((v) => Object.is(g.value, v));61 expect(index).not.toBe(-1);62 notSeenValues.splice(index, 1);63 }64 expect(notSeenValues).toEqual([]);65 }66 )67 ));68 it('should produce a cloneable instance if provided value is cloneable', () => {69 // Arrange70 const expectedBiasFactor = 48;71 const cloneable = Object.defineProperty([], cloneMethod, { value: jest.fn() });72 const { instance: mrng } = fakeRandom();73 // Act74 const arb = new ConstantArbitrary([cloneable]);75 const g = arb.generate(mrng, expectedBiasFactor);76 // Assert77 expect(g.hasToBeCloned).toBe(true);78 });79 it('should clone cloneable instances for each access', () => {80 // Arrange81 const expectedBiasFactor = 48;82 const cloneMethodImpl = jest.fn();83 const cloneable = Object.defineProperty([], cloneMethod, { value: cloneMethodImpl });84 cloneMethodImpl.mockReturnValue(cloneable); // in reality it should be a clone of it, not itself85 const { instance: mrng } = fakeRandom();86 // Act87 const arb = new ConstantArbitrary([cloneable]);88 const g = arb.generate(mrng, expectedBiasFactor);89 expect(cloneMethodImpl).not.toHaveBeenCalled();90 // Assert91 g.value;92 expect(cloneMethodImpl).toHaveBeenCalledTimes(1);93 g.value;94 expect(cloneMethodImpl).toHaveBeenCalledTimes(2);95 });96 });97 describe('canShrinkWithoutContext', () => {98 it("should mark value as 'canShrinkWithoutContext' whenever one of the original values is equal regarding Object.is", () =>99 fc.assert(100 fc.property(fc.array(fc.anything(), { minLength: 1 }), fc.nat(), (values, mod) => {101 // Arrange102 const selectedValue = values[mod % values.length];103 // Act104 const arb = new ConstantArbitrary(values);105 const out = arb.canShrinkWithoutContext(selectedValue);106 // Assert107 expect(out).toBe(true);108 })109 ));110 it('should not detect values not equal regarding to Object.is', () => {111 // Arrange112 const values: unknown[] = [0, [], {}, ''];113 const selectedValue: unknown = [];114 // Act115 const arb = new ConstantArbitrary<unknown>(values);116 const out = arb.canShrinkWithoutContext(selectedValue);117 // Assert118 expect(out).toBe(false); // Object.is([], []) is falsy119 });120 });121 describe('shrink', () => {122 it('should shrink towards the first value if it was not already this one and to nil otherwise', () =>123 fc.assert(124 fc.property(fc.array(fc.anything(), { minLength: 1 }), fc.nat(), (values, mod) => {125 // Arrange126 const { instance: mrng, nextInt } = fakeRandom();127 nextInt.mockImplementation((a, b) => a + (mod % (b - a + 1)));128 // Act129 const arb = new ConstantArbitrary(values);130 const value = arb.generate(mrng, undefined);131 const shrinks = [...arb.shrink(value.value, value.context)];132 // Assert133 if (Object.is(value.value, values[0])) {134 expect(shrinks.map((v) => v.value)).toEqual([]);135 } else {136 expect(shrinks.map((v) => v.value)).toEqual([values[0]]);137 }138 })139 ));140 it('should shrink towards the first value if it was not already this one and to nil otherwise even without any context', () =>141 fc.assert(142 fc.property(fc.array(fc.anything(), { minLength: 1 }), fc.nat(), (values, mod) => {143 // Arrange144 const { instance: mrng, nextInt } = fakeRandom();145 nextInt.mockImplementation((a, b) => a + (mod % (b - a + 1)));146 // Act147 const arb = new ConstantArbitrary(values);148 const value = arb.generate(mrng, undefined);149 const shrinks = [...arb.shrink(value.value, undefined)];150 // Assert151 if (Object.is(value.value, values[0])) {152 expect(shrinks.map((v) => v.value)).toEqual([]);153 } else {154 expect(shrinks.map((v) => v.value)).toEqual([values[0]]);155 }156 })157 ));158 it('should not shrink towards the first value if generated value is equal to the first one regarding `Object.is`', () => {159 // Arrange160 const { instance: mrng, nextInt } = fakeRandom();161 // Act / Assert162 const arb = new ConstantArbitrary([Number.NaN, Number.NaN, Number.NaN]);163 for (let idx = 0; idx !== 3; ++idx) {164 nextInt.mockReturnValue(idx);165 const value = arb.generate(mrng, undefined);166 expect(value.value).toBe(Number.NaN);167 const shrinks = [...arb.shrink(value.value, value.context)];168 expect(shrinks).toHaveLength(0);169 }170 });171 });172});173describe('ConstantArbitrary (integration)', () => {174 type Extra = unknown[];175 const extraParameters: fc.Arbitrary<Extra> = fc.array(fc.anything(), { minLength: 1 });176 // In other words: extra.includes(value) --but with Object.is177 const isCorrect = (value: unknown, extra: Extra) => extra.findIndex((v) => Object.is(value, v)) !== -1;178 // In other words: extra.indexOf(v1) < extra.indexOf(v2) --but with Object.is179 // If the same value has been declared twice in the `extra` once for `extra[0]` and the other for `extra[n]` (with n > 0)180 // Shrinker should never shrink `extra[n]` into `extra[0]` if they are equal regarding `Object.is`181 const isStrictlySmaller = (v1: unknown, v2: unknown, extra: Extra) =>182 extra.findIndex((v) => Object.is(v1, v)) < extra.findIndex((v) => Object.is(v2, v));183 const constantBuilder = (extra: Extra) => new ConstantArbitrary(extra);184 it('should produce the same values given the same seed', () => {185 assertProduceSameValueGivenSameSeed(constantBuilder, { extraParameters });186 });187 it('should only produce correct values', () => {188 assertProduceCorrectValues(constantBuilder, isCorrect, { extraParameters });189 });190 it('should produce values seen as shrinkable without any context', () => {191 assertProduceValuesShrinkableWithoutContext(constantBuilder, { extraParameters });192 });193 it('should preserve strictly smaller ordering in shrink', () => {194 assertShrinkProducesStrictlySmallerValue(constantBuilder, isStrictlySmaller, { extraParameters });195 });196 it('should not re-use twice the same instance of cloneable', () => {197 // Arrange198 const alreadySeenCloneable = new Set<unknown>();199 const buildCloneable = (): unknown => {200 return Object.defineProperty([], cloneMethod, { value: buildCloneable });201 };202 const arb = new ConstantArbitrary([buildCloneable()]);203 const { instance: mrng } = fakeRandom();204 // Act205 const g = arb.generate(mrng, undefined);206 const treeA = buildShrinkTree(arb, g);207 const treeB = buildShrinkTree(arb, g);208 // Assert209 walkTree(treeA, (cloneable) => {210 expect(alreadySeenCloneable.has(cloneable)).toBe(false);211 alreadySeenCloneable.add(cloneable);212 });213 walkTree(treeB, (cloneable) => {214 expect(alreadySeenCloneable.has(cloneable)).toBe(false);215 alreadySeenCloneable.add(cloneable);216 });217 });...
Using AI Code Generation
1const fc = require('fast-check');2const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');3const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');4console.log(fc);5console.log(cloneMethodImpl);6console.log(cloneMethod);7const fc = require('fast-check');8const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');9const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');10console.log(fc);11console.log(cloneMethodImpl);12console.log(cloneMethod);13const fc = require('fast-check');14const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');15const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');16console.log(fc);17console.log(cloneMethodImpl);18console.log(cloneMethod);19const fc = require('fast-check');20const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');21const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');22console.log(fc);23console.log(cloneMethodImpl);24console.log(cloneMethod);25const fc = require('fast-check');26const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');27const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary');28console.log(fc);29console.log(cloneMethodImpl);30console.log(cloneMethod);31const fc = require('fast-check');32const { cloneMethodImpl } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');33const { cloneMethod } = require('fast-check/lib/check/arbitrary/definition/CloneArbitrary.js');34console.log(fc);35console.log(cloneMethodImpl);36console.log(cloneMethod);
Using AI Code Generation
1const fc = require("fast-check");2const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;3const cloneMethod = require("fast-check-monorepo").cloneMethod;4const cloneMethod1 = cloneMethodImpl();5const cloneMethod2 = cloneMethod();6console.log("Clone Method 1: ", cloneMethod1);7console.log("Clone Method 2: ", cloneMethod2);
Using AI Code Generation
1const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;2describe('test3', () => {3 it('should pass', () => {4 expect(cloneMethodImpl()).toBe(true);5 });6});7const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;8describe('test4', () => {9 it('should pass', () => {10 expect(cloneMethodImpl()).toBe(true);11 });12});13const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;14describe('test5', () => {15 it('should pass', () => {16 expect(cloneMethodImpl()).toBe(true);17 });18});19const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;20describe('test6', () => {21 it('should pass', () => {22 expect(cloneMethodImpl()).toBe(true);23 });24});25const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;26describe('test7', () => {27 it('should pass', () => {28 expect(cloneMethodImpl()).toBe(true);29 });30});31const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;32describe('test8', () => {33 it('should pass', () => {34 expect(cloneMethodImpl()).toBe(true);35 });36});37const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;38describe('test9', () => {39 it('should pass', () => {40 expect(cloneMethodImpl()).toBe(true);41 });42});43const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;44describe('test10', () => {45 it('should pass', () => {46 expect(cloneMethodImpl()).toBe(true);47 });48});
Using AI Code Generation
1const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;2const myMethod = function (a,b,c) { return a+b+c; };3const myMethodCloned = cloneMethodImpl(myMethod);4console.log('myMethodCloned(1,2,3) = ' + myMethodCloned(1,2,3));5const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;6const myMethod = function (a,b,c) { return a+b+c; };7const myMethodCloned = cloneMethodImpl(myMethod);8console.log('myMethodCloned(1,2,3) = ' + myMethodCloned(1,2,3));9const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;10const myMethod = function (a,b,c) { return a+b+c; };11const myMethodCloned = cloneMethodImpl(myMethod);12console.log('myMethodCloned(1,2,3) = ' + myMethodCloned(1,2,3));13const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;14const myMethod = function (a,b,c) { return a+b+c; };15const myMethodCloned = cloneMethodImpl(myMethod);16console.log('myMethodCloned(1,2,3) = ' + myMethodCloned(1,2,3));17const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl;18const myMethod = function (a,b,c) { return a+b+c; };19const myMethodCloned = cloneMethodImpl(myMethod);20console.log('myMethodCloned(1,2,3) = ' + myMethodCloned(1,2,3));21const cloneMethodImpl = require('fast-check-monorepo').cloneMethodImpl
Using AI Code Generation
1const fastCheck = require("fast-check");2const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;3const obj = { a: 1, b: 2, c: 3 };4const clone = cloneMethod(obj);5console.log(clone);6const fastCheck = require("fast-check");7const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;8const obj = { a: 1, b: 2, c: 3 };9const clone = cloneMethod(obj);10console.log(clone);11const fastCheck = require("fast-check");12const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;13const obj = { a: 1, b: 2, c: 3 };14const clone = cloneMethod(obj);15console.log(clone);16const fastCheck = require("fast-check");17const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;18const obj = { a: 1, b: 2, c: 3 };19const clone = cloneMethod(obj);20console.log(clone);21const fastCheck = require("fast-check");22const cloneMethodImpl = require("fast-check-monorepo").cloneMethodImpl;
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!