Files
descrybe/apps/web/src/lib/activation.test.ts
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

131 lines
4.1 KiB
TypeScript

/**
* Activation checklist unit tests (node:test).
* Plan-gated optional store-connect + workspace cursor (no $lib / i18n).
*
* Run from apps/web:
* node --experimental-strip-types --test src/lib/activation.test.ts
*/
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
activationIndexFromWorkspace,
visibleActivationSteps,
type ActivationStepRef
} from "./activation/workspace.ts";
const FULL_STEPS: ActivationStepRef[] = [
{ id: "enable-fields" },
{ id: "connect-source" },
{ id: "map" },
{ id: "sync-sample" },
{ id: "process" },
{ id: "store-connect", optional: true, feature: "stores.hub" },
{ id: "export" }
];
describe("visibleActivationSteps", () => {
it("includes store-connect when stores.hub is allowed", () => {
const steps = visibleActivationSteps(FULL_STEPS, () => true);
assert.ok(steps.some((s) => s.id === "store-connect"));
assert.equal(steps.find((s) => s.id === "store-connect")?.optional, true);
assert.equal(steps.find((s) => s.id === "store-connect")?.feature, "stores.hub");
});
it("hides store-connect when stores.hub is denied (A1-safe)", () => {
const steps = visibleActivationSteps(FULL_STEPS, (key) => key !== "stores.hub");
assert.equal(
steps.some((s) => s.id === "store-connect"),
false
);
assert.deepEqual(
steps.map((s) => s.id),
["enable-fields", "connect-source", "map", "sync-sample", "process", "export"]
);
});
it("places store-connect after process and before export", () => {
const ids = FULL_STEPS.map((s) => s.id);
assert.equal(ids.indexOf("store-connect"), ids.indexOf("process") + 1);
assert.equal(ids.indexOf("export"), ids.indexOf("store-connect") + 1);
});
});
describe("activationIndexFromWorkspace", () => {
const throughProcess = {
hasEnabledFields: true,
hasSource: true,
hasMapping: true,
hasSyncedSample: true,
hasProcessed: true
};
it("stops on optional store-connect when no store and no later required evidence", () => {
const steps = visibleActivationSteps(FULL_STEPS, () => true);
const count = activationIndexFromWorkspace(throughProcess, steps);
assert.equal(count, steps.findIndex((s) => s.id === "store-connect"));
});
it("does not block export when optional store is incomplete", () => {
const steps = visibleActivationSteps(FULL_STEPS, () => true);
const count = activationIndexFromWorkspace(
{ ...throughProcess, hasExport: true },
steps
);
assert.equal(count, steps.findIndex((s) => s.id === "export") + 1);
});
it("advances past store-connect when a store is connected", () => {
const steps = visibleActivationSteps(FULL_STEPS, () => true);
const count = activationIndexFromWorkspace(
{ ...throughProcess, hasStoreConnect: true },
steps
);
assert.equal(count, steps.findIndex((s) => s.id === "export"));
});
it("skips store evidence when step is gated out", () => {
const steps = visibleActivationSteps(FULL_STEPS, (key) => key !== "stores.hub");
const count = activationIndexFromWorkspace(
{ ...throughProcess, hasExport: true },
steps
);
assert.equal(count, steps.length);
});
});
describe("activation Continue destinations", () => {
/** Mirror of ACTIVATION_STEP_DEFS hrefs — keep in sync with activation/steps.ts. */
const CONTINUE_HREFS: Record<string, string> = {
"enable-fields": "/standard-fields",
"connect-source": "/feeds?add=1",
map: "/feeds?focus=map",
"sync-sample": "/feeds?focus=sync",
process: "/products?type=raw&status=unprocessed",
"store-connect": "/stores/wizard",
export: "/export-feeds"
};
it("keeps feed-first connect-source away from the stores wizard", () => {
assert.match(CONTINUE_HREFS["connect-source"], /^\/feeds/);
assert.doesNotMatch(CONTINUE_HREFS["connect-source"], /stores/);
assert.equal(CONTINUE_HREFS["store-connect"], "/stores/wizard");
});
it("matches the checklist sequence destinations", () => {
assert.deepEqual(
FULL_STEPS.map((s) => CONTINUE_HREFS[s.id]),
[
"/standard-fields",
"/feeds?add=1",
"/feeds?focus=map",
"/feeds?focus=sync",
"/products?type=raw&status=unprocessed",
"/stores/wizard",
"/export-feeds"
]
);
});
});