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 { AssetRelationship } from "./asset-relationship.aggregate"; import { AssetDefinitionValues } from "./value-objects/asset-definition-values.vo"; import type { RelationshipValuesData } from "./value-objects/asset-relationship-values.vo"; import { AssetRelationshipValues } from "./value-objects/asset-relationship-values.vo"; const sourceId = UniqueID.generateNewID().toPrimitive(); const targetId = UniqueID.generateNewID().toPrimitive(); const typeId = UniqueID.generateNewID().toPrimitive(); function input(symmetric = false): RelationshipValuesData { return { sourceId, targetId, typeId, name: " Alojado en ", inverseName: " Aloja ", symmetric, notes: " rack 1 ", }; } function values(data = input()) { const result = AssetRelationshipValues.create(data); assert.ok(result.isSuccess); return result.data; } test("Las relaciones validan sus extremos, normalizan nombres y distinguen dirección", () => { const first = values(); assert.equal(first.toPrimitive().name, "Alojado en"); assert.equal(first.notes, "rack 1"); assert.notEqual( first.key(), values({ ...input(), sourceId: targetId, targetId: sourceId }).key() ); const symmetric = values(input(true)); assert.equal( symmetric.key(), values({ ...input(true), sourceId: targetId, targetId: sourceId }).key() ); assert.equal(symmetric.toPrimitive().inverseName, "Alojado en"); const self = AssetRelationshipValues.create({ ...input(), targetId: sourceId }); assert.ok(!self.isSuccess); assert.equal(self.error.code, "SELF_RELATIONSHIP"); assert.ok(!AssetRelationshipValues.create({ ...input(), targetId: "bad" }).isSuccess); assert.ok(!AssetRelationshipValues.create({ ...input(), inverseName: " " }).isSuccess); assert.ok(!AssetRelationshipValues.create({ ...input(), notes: "x".repeat(10001) }).isSuccess); assert.ok(Object.isFrozen(first)); }); test("Retirar conserva UUID, extremos y auditoría; repetir la retirada no modifica el historial", () => { const company = UniqueID.generateNewID(); const actor = UniqueID.generateNewID(); const otherActor = UniqueID.generateNewID(); const created = AssetRelationship.create(company, values(), actor, "2026-10-04T10:00:00.000Z"); assert.ok(created.isSuccess); const link = created.data; assert.equal(link.id.toPrimitive().charAt(14), "7"); assert.ok(link.active); assert.ok(!link.end(otherActor, "2026-10-03T10:00:00.000Z").isSuccess); const ended = link.end(otherActor, "2026-10-04T11:00:00.000Z"); assert.ok(ended.isSuccess); assert.equal(ended.data.active, false); assert.ok(ended.data.id.equals(link.id)); assert.equal(ended.data.values, link.values); assert.ok(ended.data.createdBy.equals(actor)); assert.ok(ended.data.endedBy.getOrUndefined()?.equals(otherActor)); const retry = ended.data.end(actor, "2026-10-04T12:00:00.000Z"); assert.ok(retry.isSuccess); assert.equal(retry.data, ended.data); assert.ok(link.active); }); test("Tipos de relación de serie protegidos, ámbito de compañía y dirección fija", () => { const scope = Maybe.some(UniqueID.generateNewID()); const other = Maybe.some(UniqueID.generateNewID()); let catalog = seedAssetCatalog(AssetCatalog.create()); const stock = catalog.definitions.find((item) => item.values.data.kind === "relation"); assert.ok(stock); const spec = { kind: "relation", name: "Conectado a", inverseName: "Conectado a", description: "", symmetric: true, } as const; const custom = AssetDefinitionValues.create({ ...spec, name: "Replica a", inverseName: "Replicado desde", symmetric: false, }); assert.ok(custom.isSuccess); const protectedChange = catalog.save(Maybe.none(), Maybe.some(stock.id), custom.data); assert.ok(!protectedChange.isSuccess); assert.equal(protectedChange.error.code, "BUILTIN_PROTECTED"); const status = catalog.setActive(scope, stock.id, false); assert.ok(status.isSuccess); catalog = status.data; assert.equal(catalog.active(stock, scope), false); assert.equal(catalog.active(stock, other), true); const added = catalog.save(scope, Maybe.none(), custom.data); assert.ok(added.isSuccess); catalog = added.data; const item = catalog.definitions.at(-1); assert.ok(item); assert.equal( catalog.visible(other).some((entry) => entry.id.equals(item.id)), false ); const converted = AssetDefinitionValues.create({ ...spec, name: "Replica a" }); assert.ok(converted.isSuccess); const rejected = catalog.save(scope, Maybe.some(item.id), converted.data); assert.ok(!rejected.isSuccess); assert.equal(rejected.error.code, "RELATION_DIRECTION_FIXED"); const unchanged = catalog.save(scope, Maybe.some(item.id), custom.data); assert.ok(unchanged.isSuccess); assert.equal(unchanged.data, catalog); });