Ctrl K
ComunidadGuías…

test/shared/admin-surface.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 type { AdminDestinationId } from "#shared/admin-surface/ids.ts";
import {
  ADMIN_SURFACE,
  adminDestination,
  adminDestinationAllowed,
  adminDestinationAt,
  adminPath,
  adminPattern,
  adminRecordPath,
  afterSavePath,
} from "#shared/admin-surface.ts";

describe("the pattern a route declares", () => {
  test("is the one the surface holds, for every route", () => {
    // adminPattern names the literal its declaration wrote, which the fold
    // cannot carry through as a type. This reads all of them back, so the
    // name and the value can never drift apart unnoticed.
    const wrong = Object.entries(ADMIN_SURFACE.destinations)
      .filter(
        ([id, destination]) =>
          adminPattern(id as AdminDestinationId) !== destination.pattern,
      )
      .map(([id]) => id);
    expect(wrong).toEqual([]);
  });

  test("says which id was never declared", () => {
    // Reached only past the types, which is how a page definition naming a
    // route that does not exist shows itself.
    expect(() => adminPattern("nowhere" as AdminDestinationId)).toThrow(
      'No admin route is declared as "nowhere"',
    );
  });

  test("refuses to mint a record URL for a route taking two parameters", () => {
    // An entity page names the route it serves, so a route that needs a
    // second value cannot be one, and saying so at the page definition beats
    // minting a URL with a parameter still in it.
    expect(() => adminRecordPath("answerEdit", 7)).toThrow(
      'Admin route "answerEdit" does not address one record',
    );
  });

  test("refuses to mint a record URL for a route taking none", () => {
    // A collection's own path names no record either, and quietly returning
    // it would send every record to the same page.
    expect(() => adminRecordPath("holidays", 7)).toThrow(
      'Admin route "holidays" does not address one record',
    );
  });

  test("mints a record URL whatever the route calls its parameter", () => {
    expect(adminRecordPath("attendee", 7)).toBe("/admin/attendees/7");
    expect(adminRecordPath("holiday", 7)).toBe("/admin/holidays/7");
  });

  test("says which path has no route", () => {
    expect(() => adminDestinationAt("/admin/nowhere")).toThrow(
      'No admin route is declared at "/admin/nowhere"',
    );
  });

  test("keeps the parameters the route takes", () => {
    expect(adminPattern("holiday")).toBe("/admin/holidays/:id");
    expect(adminPattern("holidays")).toBe("/admin/holidays");
  });
});

describe("admin surface paths", () => {
  test("fills every named route parameter", () => {
    expect(adminPath("answerEdit", { answerId: 9, id: 42 })).toBe(
      "/admin/questions/42/answers/9/edit",
    );
  });

  test("allows write forms only for their audience while writable", () => {
    expect(adminDestinationAllowed("modifierEdit", "manager", false)).toBe(
      true,
    );
    expect(adminDestinationAllowed("modifierEdit", "editor", false)).toBe(
      false,
    );
    expect(adminDestinationAllowed("modifierEdit", "owner", true)).toBe(false);
  });

  test("allows view routes in read-only mode", () => {
    expect(adminDestinationAllowed("modifiers", "manager", true)).toBe(true);
  });

  test("takes each route's intent from the group it is declared in", () => {
    expect(adminDestination("modifiers").intent).toBe("view");
    expect(adminDestination("modifierEdit").intent).toBe("write-form");
  });

  test("gives every route the audience its area declares", () => {
    // holidayNew states no role of its own, so it takes the area's owner-only
    // audience — the same one the handler enforces.
    expect(adminDestination("holidayNew").audience).toEqual(["owner"]);
    expect(adminDestination("holidays").audience).toEqual(["owner"]);
  });
});

describe("generated CRUD save paths", () => {
  test("uses the collection list when the POST route has no override", () => {
    expect(afterSavePath(adminDestination("modifiers"), "modifiers", 3)).toBe(
      "/admin/modifiers",
    );
    expect(
      afterSavePath(adminDestination("modifierEdit"), "modifiers", 3),
    ).toBe("/admin/modifiers");
    expect(afterSavePath(adminDestination("statuses"), "statuses", 3)).toBe(
      "/admin/settings/statuses",
    );
  });

  test("uses record overrides on the create and edit POST routes", () => {
    expect(afterSavePath(adminDestination("groups"), "groups", 7)).toBe(
      "/admin/groups/7",
    );
    expect(afterSavePath(adminDestination("groupEdit"), "groups", 7)).toBe(
      "/admin/groups/7",
    );
    expect(afterSavePath(adminDestination("statusEdit"), "statuses", 9)).toBe(
      "/admin/settings/statuses/9",
    );
  });
});