Ctrl K
ComunidadGuías…

test/shared/admin-features.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 {
  ADMIN_FEATURES,
  enabledFeaturesWithUsage,
  featureBySlug,
  parseEnabledFeatures,
  serializeEnabledFeatures,
  setFeatureEnabled,
} from "#shared/admin-features.ts";

const DEFAULT_ENABLED_FEATURES = parseEnabledFeatures("");

describe("admin features", () => {
  test("defines the complete feature list in display order", () => {
    expect(ADMIN_FEATURES).toEqual([
      {
        descriptionKey: "features.site.description",
        inUseSql: null,
        key: "site",
        labelKey: "features.site.name",
        slug: "site",
      },
      {
        descriptionKey: "features.attributes.description",
        inUseSql: "EXISTS (SELECT 1 FROM attributes AS attribute)",
        key: "attributes",
        labelKey: "features.attributes.name",
        slug: "attributes",
      },
      {
        descriptionKey: "features.questions.description",
        inUseSql: "EXISTS (SELECT 1 FROM questions AS question)",
        key: "questions",
        labelKey: "features.questions.name",
        slug: "questions",
      },
      {
        descriptionKey: "features.modifiers.description",
        inUseSql: "EXISTS (SELECT 1 FROM modifiers AS modifier)",
        key: "modifiers",
        labelKey: "features.modifiers.name",
        slug: "modifiers",
      },
      {
        descriptionKey: "features.logistics.description",
        inUseSql:
          "EXISTS (SELECT 1 FROM logistics_agents AS logisticsAgent) OR EXISTS (SELECT 1 FROM listings AS listing WHERE listing.uses_logistics = 1)",
        key: "logistics",
        labelKey: "features.logistics.name",
        slug: "logistics",
      },
      {
        descriptionKey: "features.api_keys.description",
        inUseSql: "EXISTS (SELECT 1 FROM api_keys AS apiKey)",
        key: "apiKeys",
        labelKey: "features.api_keys.name",
        slug: "api-keys",
      },
      {
        descriptionKey: "features.servicing.description",
        inUseSql:
          "EXISTS (SELECT 1 FROM attendees AS attendee WHERE attendee.kind = 'servicing')",
        key: "servicing",
        labelKey: "features.servicing.name",
        slug: "servicing",
      },
      {
        descriptionKey: "features.money.description",
        inUseSql: null,
        key: "money",
        labelKey: "features.money.name",
        slug: "money",
      },
      {
        descriptionKey: "features.external_sources.description",
        inUseSql: null,
        key: "externalSources",
        labelKey: "features.external_sources.name",
        slug: "external-sources",
      },
      {
        descriptionKey: "features.invoices.description",
        inUseSql: "EXISTS (SELECT 1 FROM invoices AS invoice)",
        key: "invoices",
        labelKey: "features.invoices.name",
        slug: "invoices",
      },
    ]);
  });

  test("defaults every feature to disabled", () => {
    expect(DEFAULT_ENABLED_FEATURES).toEqual({
      apiKeys: false,
      attributes: false,
      externalSources: false,
      invoices: false,
      logistics: false,
      modifiers: false,
      money: false,
      questions: false,
      servicing: false,
      site: false,
    });
  });

  test("uses the defaults when the setting has not been stored", () => {
    expect(parseEnabledFeatures("")).toEqual(DEFAULT_ENABLED_FEATURES);
  });

  test("serializes and parses the complete strict setting", () => {
    const enabled = setFeatureEnabled(
      DEFAULT_ENABLED_FEATURES,
      "apiKeys",
      true,
    );
    expect(parseEnabledFeatures(serializeEnabledFeatures(enabled))).toEqual({
      ...DEFAULT_ENABLED_FEATURES,
      apiKeys: true,
    });
  });

  test("does not mutate the previous setting when one feature changes", () => {
    const enabled = setFeatureEnabled(DEFAULT_ENABLED_FEATURES, "money", true);
    expect(enabled).not.toBe(DEFAULT_ENABLED_FEATURES);
    expect(DEFAULT_ENABLED_FEATURES.money).toBe(false);
    expect(enabled.money).toBe(true);
  });

  test("shows configured features and features with saved records", () => {
    const configured = setFeatureEnabled(
      DEFAULT_ENABLED_FEATURES,
      "money",
      true,
    );
    const usage = setFeatureEnabled(
      DEFAULT_ENABLED_FEATURES,
      "modifiers",
      true,
    );
    expect(enabledFeaturesWithUsage(configured, usage)).toEqual({
      ...DEFAULT_ENABLED_FEATURES,
      modifiers: true,
      money: true,
    });
  });

  test("rejects malformed, extra, and non-boolean settings", () => {
    const invalidValues = [
      "not json",
      JSON.stringify({ ...DEFAULT_ENABLED_FEATURES, money: "true" }),
      JSON.stringify({ ...DEFAULT_ENABLED_FEATURES, unknown: false }),
    ];
    for (const value of invalidValues) {
      expect(() => parseEnabledFeatures(value), value).toThrow();
    }
  });

  test("reads a feature the stored setting lacks as off", () => {
    expect(parseEnabledFeatures(JSON.stringify({ money: true }))).toEqual({
      ...DEFAULT_ENABLED_FEATURES,
      money: true,
    });
  });

  test("identifies an invalid setting without retaining its value", () => {
    let thrown: unknown;
    try {
      parseEnabledFeatures(
        JSON.stringify({ ...DEFAULT_ENABLED_FEATURES, money: "true" }),
      );
    } catch (error) {
      thrown = error;
    }
    const error = thrown as Error;
    expect(error.message).toBe(
      "Invalid stored JSON in settings.enabled_features: Stored value does not match its schema",
    );
    // The error carries no cause, so the stored value does not travel with it.
    expect(error.cause).toBe(undefined);
  });

  test("names the setting when serialization rejects invalid features", () => {
    expect(() =>
      serializeEnabledFeatures({ money: "yes" } as unknown as Parameters<
        typeof serializeEnabledFeatures
      >[0]),
    ).toThrow(/^Invalid value for stored JSON in settings\.enabled_features$/);
  });

  test("finds a feature by slug and returns null for an unknown slug", () => {
    expect(featureBySlug("site")?.key).toBe("site");
    expect(featureBySlug("unknown")).toBeNull();
  });
});