Skip to content

simpleFraction arbitrary #6313

@dmurvihill

Description

@dmurvihill

💡 Idea

Generates pairs of natural numbers.

You can constrain the maximum ratio between the numbers in either or
both directions. By default, zero is allowed in either or both
positions, but can be prevented with noZeroDenom.

Motivation

I developed this to help test code that was using setInterval. My code needs to support arbitrary intervals for an arbitrarily long time. To limit test execution time, I needed to enforce a maximum number of times the interval code would execute.

Are you interested in this function?

Example

const arbTestTiming = simpleFraction({ inverseMin: maxTestedIntervals })

  it.only.prop([fc.scheduler(), arbTestTiming])(
    'should poll at the interval',
    async (scheduler, [interval, elapsed]) => {
      const poll = jest.fn().mockImplementation(() =>
        scheduler.schedule(Promise.resolve()),
      );
      const pm = new PolledValue<void>(poll, interval);
      try {
        poll.mockClear();
        await jest.advanceTimersByTimeAsync(elapsed);
        expect(poll).toHaveBeenCalledTimes(Math.floor(elapsed / interval));
      } finally {
        await endAndWait(pm);
      }
    },
  );

Implementation

/** Generates pairs of natural numbers.
 *
 * You can constrain the maximum ratio between the numbers in either or
 * both directions. By default, zero is allowed in either or both
 * positions, but can be prevented with `noZeroDenom`.
 * */
function simpleFraction(constraints?: SimpleFractionConstraints) {
  if (constraints?.inverseMin < 0) {
    throw new Error(`Expected positive inverseMin; got ${constraints.inverseMin}`)
  } else if (constraints?.max < 0) {
    throw new Error(`Expected positive max; got ${constraints.max}`)
  }
  return fc.tuple(fc.nat(), fc.nat())
    .filter(([, den]) => !(constraints?.noZeroDenom) || den !== 0)
    .map(([num, den]) => [
      constraints?.max ? Math.min(num, den * constraints.max) : num,
      constraints?.inverseMin ? Math.min(den, num * constraints.inverseMin) : den,
    ]);
}


interface SimpleFractionConstraints {

  /**
   * Maximum ratio between the numerator and the denominator.
   * Set higher to get bigger fractions.
   * */
  max?: number,

  /**
   * Maximum ratio between the denominator and the numerator. Set higher
   * to get smaller fractions.
   * */
  inverseMin?: number,

  /**
   * Allow values with a zero denominator. Defaults to **true**.
   */
  noZeroDenom?: boolean,
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions