2026-10-04 16:36:09 +00:00
|
|
|
import assert from "node:assert/strict";
|
|
|
|
|
import { test } from "node:test";
|
|
|
|
|
|
|
|
|
|
import { UniqueID } from "@repo/rdx-ddd";
|
|
|
|
|
import { Maybe } from "@repo/rdx-utils";
|
|
|
|
|
|
|
|
|
|
import { AssetCatalog } from "./asset-catalog.aggregate";
|
|
|
|
|
import { seedAssetCatalog } from "./asset-catalog-seed";
|
|
|
|
|
import type { AssetDefinitionSpec } from "./asset-definition";
|
|
|
|
|
import { AssetDefinitionValues } from "./value-objects/asset-definition-values";
|
|
|
|
|
|
|
|
|
|
const global = Maybe.none<UniqueID>();
|
|
|
|
|
function values(spec: AssetDefinitionSpec) {
|
|
|
|
|
const result = AssetDefinitionValues.create(spec);
|
|
|
|
|
assert.ok(result.isSuccess);
|
|
|
|
|
return result.data;
|
|
|
|
|
}
|
|
|
|
|
function field(name: string) {
|
|
|
|
|
return values({ kind: "field", name, type: "text", unit: "", choices: [], description: "" });
|
|
|
|
|
}
|
|
|
|
|
function changed(result: ReturnType<AssetCatalog["save"]>) {
|
|
|
|
|
assert.ok(result.isSuccess);
|
|
|
|
|
return result.data;
|
|
|
|
|
}
|
|
|
|
|
test("el catálogo inicial es idempotente, con UUID propios y características opcionales", () => {
|
|
|
|
|
const catalog = seedAssetCatalog(AssetCatalog.create());
|
2026-10-04 19:04:14 +00:00
|
|
|
assert.equal(catalog.definitions.length, 47);
|
2026-10-04 16:36:09 +00:00
|
|
|
assert.equal(seedAssetCatalog(catalog), catalog);
|
|
|
|
|
const ids = [
|
|
|
|
|
catalog.id,
|
|
|
|
|
...catalog.definitions.map((item) => item.id),
|
|
|
|
|
...catalog.definitions.flatMap((item) => item.bindings.map((binding) => binding.id)),
|
|
|
|
|
].map((id) => id.toPrimitive());
|
|
|
|
|
assert.equal(new Set(ids).size, ids.length);
|
|
|
|
|
assert.ok(ids.every((id) => id.charAt(14) === "7"));
|
|
|
|
|
const templates = catalog.definitions.filter((item) => item.values.data.kind === "template");
|
|
|
|
|
assert.equal(templates.length, 12);
|
|
|
|
|
assert.ok(templates.every((item) => item.bindings.every((field) => !field.required)));
|
|
|
|
|
const rehydrated = AssetCatalog.rehydrate(
|
|
|
|
|
{ definitions: catalog.definitions, availability: catalog.availability },
|
|
|
|
|
catalog.id
|
|
|
|
|
);
|
|
|
|
|
assert.ok(rehydrated.id.equals(catalog.id));
|
|
|
|
|
assert.ok(rehydrated.definitions[0]?.id.equals(catalog.definitions[0]?.id));
|
|
|
|
|
const stock = catalog.definitions[0];
|
|
|
|
|
assert.ok(stock);
|
|
|
|
|
const protectedResult = catalog.save(global, Maybe.some(stock.id), field("Cambio"));
|
|
|
|
|
assert.ok(!protectedResult.isSuccess);
|
|
|
|
|
assert.equal(protectedResult.error.code, "BUILTIN_PROTECTED");
|
|
|
|
|
});
|
|
|
|
|
test("la disponibilidad por compañía conserva el global y los campos desactivados", () => {
|
|
|
|
|
let catalog = seedAssetCatalog(AssetCatalog.create());
|
|
|
|
|
const first = Maybe.some(UniqueID.generateNewID());
|
|
|
|
|
const second = Maybe.some(UniqueID.generateNewID());
|
|
|
|
|
const stock = catalog.definitions[0];
|
|
|
|
|
assert.ok(stock);
|
|
|
|
|
catalog = changed(catalog.setActive(first, stock.id, false));
|
|
|
|
|
assert.equal(catalog.active(stock, first), false);
|
|
|
|
|
assert.equal(catalog.active(stock, second), true);
|
|
|
|
|
assert.equal(stock.active, true);
|
2026-10-04 19:04:14 +00:00
|
|
|
assert.equal(catalog.definitions.length, 47);
|
2026-10-04 16:36:09 +00:00
|
|
|
const overrideId = catalog.availability[0]?.id;
|
|
|
|
|
assert.ok(overrideId);
|
|
|
|
|
assert.equal(changed(catalog.setActive(first, stock.id, false)), catalog);
|
|
|
|
|
catalog = changed(catalog.setActive(first, stock.id, null));
|
|
|
|
|
assert.equal(catalog.active(stock, first), true);
|
|
|
|
|
assert.ok(catalog.availability[0]?.id.equals(overrideId));
|
|
|
|
|
catalog = changed(catalog.setActive(global, stock.id, false));
|
|
|
|
|
assert.equal(seedAssetCatalog(catalog), catalog);
|
|
|
|
|
assert.equal(catalog.active(catalog.definitions[0] ?? stock, first), false);
|
|
|
|
|
});
|
|
|
|
|
test("las plantillas validan ámbito, campos activos e identidad estable al editar", () => {
|
|
|
|
|
let catalog = seedAssetCatalog(AssetCatalog.create());
|
|
|
|
|
const company = Maybe.some(UniqueID.generateNewID());
|
|
|
|
|
const other = Maybe.some(UniqueID.generateNewID());
|
|
|
|
|
catalog = changed(catalog.save(company, Maybe.none(), field("Campo local")));
|
|
|
|
|
const local = catalog.definitions.at(-1);
|
|
|
|
|
assert.ok(local);
|
|
|
|
|
const template = values({
|
|
|
|
|
kind: "template",
|
|
|
|
|
name: "Plantilla local",
|
|
|
|
|
description: "",
|
|
|
|
|
fields: [{ fieldId: local.id.toPrimitive(), required: false }],
|
|
|
|
|
});
|
|
|
|
|
assert.ok(!catalog.save(global, Maybe.none(), template).isSuccess);
|
|
|
|
|
assert.ok(!catalog.save(other, Maybe.none(), template).isSuccess);
|
|
|
|
|
catalog = changed(catalog.save(company, Maybe.none(), template));
|
|
|
|
|
const saved = catalog.definitions.at(-1);
|
|
|
|
|
assert.ok(saved);
|
|
|
|
|
assert.equal(changed(catalog.save(company, Maybe.some(saved.id), template)), catalog);
|
|
|
|
|
const updated = values({ ...template.data, name: "Otra denominación" });
|
|
|
|
|
catalog = changed(catalog.save(company, Maybe.some(saved.id), updated));
|
|
|
|
|
const edited = catalog.definitions.at(-1);
|
|
|
|
|
assert.ok(edited);
|
|
|
|
|
assert.ok(edited.id.equals(saved.id));
|
|
|
|
|
assert.ok(edited.bindings[0]?.id.equals(saved.bindings[0]?.id));
|
|
|
|
|
catalog = changed(catalog.setActive(company, local.id, false));
|
|
|
|
|
assert.ok(
|
|
|
|
|
!catalog.save(company, Maybe.none(), values({ ...template.data, name: "Nueva" })).isSuccess
|
|
|
|
|
);
|
|
|
|
|
assert.ok(catalog.save(company, Maybe.some(saved.id), updated).isSuccess);
|
|
|
|
|
assert.ok(!catalog.visible(other).some((item) => item.id.equals(local.id)));
|
|
|
|
|
});
|
|
|
|
|
test("los campos validan listas, igualdad semántica, duplicados y tipo fijo", () => {
|
|
|
|
|
const list: AssetDefinitionSpec = {
|
|
|
|
|
kind: "field",
|
|
|
|
|
name: "Batería",
|
|
|
|
|
description: "",
|
|
|
|
|
type: "choice",
|
|
|
|
|
unit: "",
|
|
|
|
|
choices: ["Buena", "Sustituir"],
|
|
|
|
|
};
|
|
|
|
|
assert.ok(!AssetDefinitionValues.create({ ...list, choices: [] }).isSuccess);
|
|
|
|
|
assert.ok(!AssetDefinitionValues.create({ ...list, choices: ["Buena", " buena "] }).isSuccess);
|
|
|
|
|
assert.ok(!AssetDefinitionValues.create({ ...list, type: "text" }).isSuccess);
|
|
|
|
|
const frozen = values(list);
|
|
|
|
|
assert.ok(Object.isFrozen(frozen.data));
|
|
|
|
|
if (frozen.data.kind === "field") {
|
|
|
|
|
assert.ok(Object.isFrozen(frozen.data.choices));
|
|
|
|
|
}
|
|
|
|
|
let catalog = AssetCatalog.create();
|
|
|
|
|
catalog = changed(catalog.save(global, Maybe.none(), frozen));
|
|
|
|
|
const saved = catalog.definitions[0];
|
|
|
|
|
assert.ok(saved);
|
|
|
|
|
assert.ok(!catalog.save(global, Maybe.none(), values({ ...list, name: " batería " })).isSuccess);
|
|
|
|
|
assert.ok(!catalog.save(global, Maybe.some(saved.id), field("Batería")).isSuccess);
|
|
|
|
|
assert.ok(
|
|
|
|
|
!catalog.save(global, Maybe.some(saved.id), values({ ...list, choices: ["Buena"] })).isSuccess
|
|
|
|
|
);
|
|
|
|
|
assert.ok(
|
|
|
|
|
catalog.save(
|
|
|
|
|
global,
|
|
|
|
|
Maybe.some(saved.id),
|
|
|
|
|
values({ ...list, choices: [...list.choices, "Desconocida"] })
|
|
|
|
|
).isSuccess
|
|
|
|
|
);
|
|
|
|
|
});
|