typestar

test-suite.js in JavaScript

A whole test file: suites, hooks, table cases, mocks and fake timers.

#!/usr/bin/env node --test
import { before, beforeEach, describe, it } from "node:test";
import assert from "node:assert/strict";

class Scorer {
  #history = [];

  constructor(target = 90) {
    if (target <= 0) throw new RangeError("target must be positive");
    this.target = target;
  }

  stars(tpm, accuracy) {
    if (accuracy < 0 || accuracy > 100) {
      throw new RangeError(`accuracy out of range: ${accuracy}`);
    }
    let earned = 1;
    if (accuracy >= 95) earned = 2;
    if (accuracy >= 98 && tpm >= this.target) earned = 3;
    this.#history.push(earned);
    return earned;
  }

  get best() {
    return this.#history.length ? Math.max(...this.#history) : 0;
  }

  async save(store) {
    return store.write(this.#history);
  }
}

describe("Scorer", () => {
  let scorer;

  before(() => assert.equal(typeof Scorer, "function"));
  beforeEach(() => { scorer = new Scorer(90); });

  describe("stars", () => {
    const cases = [
      { name: "slow but clean", tpm: 60, accuracy: 99, want: 2 },
      { name: "fast and clean", tpm: 95, accuracy: 99, want: 3 },
      { name: "fast and sloppy", tpm: 95, accuracy: 80, want: 1 },
      { name: "exactly at the bar", tpm: 90, accuracy: 98, want: 3 },
    ];

    for (const { name, tpm, accuracy, want } of cases) {
      it(name, () => assert.equal(scorer.stars(tpm, accuracy), want));
    }

    it("rejects an impossible accuracy", () => {
      assert.throws(() => scorer.stars(90, 140), {
        name: "RangeError",
        message: /out of range/,
      });
    });
  });

  describe("best", () => {
    it("is zero before any run", () => assert.equal(scorer.best, 0));

    it("keeps the highest", () => {
      scorer.stars(95, 99);
      scorer.stars(10, 50);
      assert.equal(scorer.best, 3);
    });
  });

  describe("save", () => {
    it("hands the history to the store", async (t) => {
      const write = t.mock.fn(async () => "written");
      scorer.stars(95, 99);

      assert.equal(await scorer.save({ write }), "written");
      assert.equal(write.mock.callCount(), 1);
      assert.deepEqual(write.mock.calls[0].arguments, [[3]]);
    });
  });

  it("refuses a zero target", () => {
    assert.throws(() => new Scorer(0), /positive/);
  });
});

How it works

  1. The code under test sits at the top, so the file stands alone.
  2. Cases live in an array, so adding one is a single line.
  3. Mocks and fake timers keep it fast and deterministic.

Keywords and builtins used here

The run, in numbers

Lines
83
Characters to type
2000
Tokens
588
Three-star pace
110 tpm

At the three-star pace of 110 tokens a minute, this run takes about 321 seconds.

Type this snippet

Step 1 of 1 in Encore, step 9 of 9 in Testing with node:test.

← Previous