1import { describe, expect, test } from "alchemy-test";
2import { fromPath, FQN_SEPARATOR, parseFqn, toFqn, toPath } from "../src/FQN";
3import type { NamespaceNode } from "../src/Namespace";
4
5describe("FQN", { tags: ["unit", "local"] }, () => {
6 describe("toPath", () => {
7 test("returns empty array for undefined namespace", () => {
8 expect(toPath(undefined)).toEqual([]);
9 });
10
11 test("returns single element for root namespace", () => {
12 const ns: NamespaceNode = { Id: "Root" };
13 expect(toPath(ns)).toEqual(["Root"]);
14 });
15
16 test("returns path from root to leaf", () => {
17 const ns: NamespaceNode = {
18 Id: "Child",
19 Parent: {
20 Id: "Parent",
21 Parent: { Id: "Root" },
22 },
23 };
24 expect(toPath(ns)).toEqual(["Root", "Parent", "Child"]);
25 });
26 });
27
28 describe("toFqn", () => {
29 test("returns logicalId for undefined namespace", () => {
30 expect(toFqn(undefined, "MyResource")).toBe("MyResource");
31 });
32
33 test("returns namespace-qualified name", () => {
34 const ns: NamespaceNode = { Id: "Parent" };
35 expect(toFqn(ns, "MyResource")).toBe(`Parent${FQN_SEPARATOR}MyResource`);
36 });
37
38 test("handles deep namespace", () => {
39 const ns: NamespaceNode = {
40 Id: "Child",
41 Parent: { Id: "Parent" },
42 };
43 expect(toFqn(ns, "MyResource")).toBe(
44 `Parent${FQN_SEPARATOR}Child${FQN_SEPARATOR}MyResource`,
45 );
46 });
47 });
48
49 describe("parseFqn", () => {
50 test("parses simple logicalId", () => {
51 expect(parseFqn("MyResource")).toEqual({
52 path: [],
53 logicalId: "MyResource",
54 });
55 });
56
57 test("parses namespaced FQN", () => {
58 expect(parseFqn("Parent/Child/MyResource")).toEqual({
59 path: ["Parent", "Child"],
60 logicalId: "MyResource",
61 });
62 });
63
64 test("parses single namespace FQN", () => {
65 expect(parseFqn("Parent/MyResource")).toEqual({
66 path: ["Parent"],
67 logicalId: "MyResource",
68 });
69 });
70 });
71
72 describe("fromPath", () => {
73 test("returns undefined for empty path", () => {
74 expect(fromPath([])).toBeUndefined();
75 });
76
77 test("returns single node for single element", () => {
78 const result = fromPath(["Root"]);
79 expect(result).toEqual({ Id: "Root", Parent: undefined });
80 });
81
82 test("returns nested nodes", () => {
83 const result = fromPath(["Root", "Parent", "Child"]);
84 expect(result).toEqual({
85 Id: "Child",
86 Parent: {
87 Id: "Parent",
88 Parent: { Id: "Root", Parent: undefined },
89 },
90 });
91 });
92 });
93
94 describe("roundtrip", () => {
95 test("toFqn -> parseFqn -> fromPath -> toFqn", () => {
96 const ns: NamespaceNode = {
97 Id: "Child",
98 Parent: { Id: "Parent" },
99 };
100 const logicalId = "MyResource";
101 const fqn = toFqn(ns, logicalId);
102 const parsed = parseFqn(fqn);
103 const reconstructedNs = fromPath(parsed.path);
104 const roundtripFqn = toFqn(reconstructedNs, parsed.logicalId);
105 expect(roundtripFqn).toBe(fqn);
106 });
107 });
108});