Ctrl K
ComunidadGuías…

test/shared/accounting/accounts.test.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import {
  attendeeAccount,
  BOOKING_FEE_INCOME,
  costAccount,
  isRowAccountType,
  isSingletonAccountType,
  modifierAccount,
  ROW_ACCOUNT_CONSTRUCTORS,
  revenueAccount,
  SINGLETON_ACCOUNTS,
  TAX_VAT,
  WORLD,
  WRITEOFF,
} from "#accounting/accounts.ts";

describe("accounting > accounts", () => {
  test("exposes the fixed singleton accounts", () => {
    expect(WORLD).toEqual({ id: "world", type: "external" });
    expect(BOOKING_FEE_INCOME).toEqual({ id: "booking", type: "fee_income" });
    expect(TAX_VAT).toEqual({ id: "vat", type: "tax" });
    expect(WRITEOFF).toEqual({ id: "default", type: "writeoff" });
  });

  // Each row builder maps its rows onto its OWN account type — a swapped `kind`
  // would silently divert money to another type's account.
  const builders: [
    name: string,
    build: (id: number) => unknown,
    type: string,
  ][] = [
    ["attendeeAccount", attendeeAccount, "attendee"],
    ["revenueAccount", revenueAccount, "revenue"],
    ["costAccount", costAccount, "cost"],
    ["modifierAccount", modifierAccount, "modifier"],
  ];

  for (const [builderName, build, type] of builders) {
    test(`${builderName} builds a ${type} account from a valid id`, () => {
      // 1 is the smallest accepted id — the boundary of the `id > 0` guard.
      expect(build(1)).toEqual({ id: "1", type });
      expect(build(3)).toEqual({ id: "3", type });
    });
  }

  const badIds: [name: string, id: number][] = [
    ["zero", 0],
    ["negative", -1],
    ["fractional", 1.5],
    ["unsafe (too large)", 2 ** 53],
    ["NaN", Number.NaN],
    ["infinite", Number.POSITIVE_INFINITY],
  ];

  for (const [builderName, build] of builders) {
    for (const [idName, id] of badIds) {
      test(`${builderName} rejects a ${idName} id`, () => {
        expect(() => build(id)).toThrow("positive safe integer");
      });
    }
  }

  describe("account-type guards", () => {
    test("isRowAccountType accepts the row-backed types only", () => {
      for (const type of ["attendee", "cost", "modifier", "revenue"]) {
        expect(isRowAccountType(type)).toBe(true);
      }
      for (const type of ["external", "fee_income", "writeoff", "", "nope"]) {
        expect(isRowAccountType(type)).toBe(false);
      }
    });

    test("isSingletonAccountType accepts the singleton types only", () => {
      for (const type of ["external", "fee_income", "tax", "writeoff"]) {
        expect(isSingletonAccountType(type)).toBe(true);
      }
      for (const type of ["attendee", "cost", "modifier", "revenue", "nope"]) {
        expect(isSingletonAccountType(type)).toBe(false);
      }
    });
  });

  describe("dispatch tables", () => {
    test("every singleton type resolves to its own account", () => {
      expect(SINGLETON_ACCOUNTS.external).toEqual(WORLD);
      expect(SINGLETON_ACCOUNTS.fee_income).toEqual(BOOKING_FEE_INCOME);
      expect(SINGLETON_ACCOUNTS.tax).toEqual(TAX_VAT);
      expect(SINGLETON_ACCOUNTS.writeoff).toEqual(WRITEOFF);
    });

    test("every row type resolves to a constructor for its own account type", () => {
      expect(ROW_ACCOUNT_CONSTRUCTORS.attendee(5)).toEqual({
        id: "5",
        type: "attendee",
      });
      expect(ROW_ACCOUNT_CONSTRUCTORS.cost(5)).toEqual({
        id: "5",
        type: "cost",
      });
      expect(ROW_ACCOUNT_CONSTRUCTORS.modifier(5)).toEqual({
        id: "5",
        type: "modifier",
      });
      expect(ROW_ACCOUNT_CONSTRUCTORS.revenue(5)).toEqual({
        id: "5",
        type: "revenue",
      });
    });
  });
});