seed.js

/**
 * Seed utilities for controlling randomness in tests. These can be overridden in tests to
 * provide predictable results.
 * @module seed
 */

/**
 * Returns a random value (<code>Math.random()</code> by default).
 * @function random
 * @returns {Number} a random number between 0 and 1.0. This can
 * be overridden in tests to control for randomness.
 *
 * @example
 * seed.random()
 * => 0.42480169934972056
 */
function random() {
  return Math.random();
}

/**
 * Returns a long value (<code>new Date().getTime()</code> by default).
 * @function timestamp
 * @returns {Number} milliseconds since the epoch. This can be
 * overridden in tests to control for time.
 *
 * @example
 * seed.timestamp()
 * => 1571246424383
 */
function timestamp() {
  return new Date().getTime();
}

/**
 * Replaces <code>seed.random</code> with a function that cycles through a fixed
 * sequence of values, looping back to the start when exhausted. Useful in tests
 * when a single constant isn't enough to drive realistic variation.
 *
 * @function sequence
 * @param {...Number} values - One or more numbers between 0 and 1.0.
 *
 * @example
 * seed.sequence(0.1, 0.5, 0.9);
 * seed.random(); // => 0.1
 * seed.random(); // => 0.5
 * seed.random(); // => 0.9
 * seed.random(); // => 0.1  (loops)
 *
 * @example <caption>Example usage in a test</caption>
 * beforeEach(() => {
 *   seed.sequence(0.1, 0.5, 0.9);  // cycles: 0.1 → 0.5 → 0.9 → 0.1 → ...
 * });
 * afterEach(() => {
 *   seed.restore();
 * });
 */
function sequence(...values) {
  let i = 0;
  seed.random = () => values[i++ % values.length];
}

/**
 * Restores the seed functions to their default implementations.
 * @function restore
 *
 * @example
 * seed.restore()
 */
function restore() {
  seed.random = random;
  seed.timestamp = timestamp;
}

const seed = {
  random,
  timestamp,
  restore,
  sequence,
};

export { seed };