import { describe, expect, it } from "@suaveplan/testing/runner"; import { createParseState } from "../../engine/ParseState.js"; import { TemplateEngine } from "../../engine/TemplateEngine.js"; import { SKIP_PLUGIN } from "../../types/index.js"; import { createStringSplitPlugin } from "./StringSplitPlugin.js"; function engine() { return new TemplateEngine().use(createStringSplitPlugin()); } describe("createStringSplitPlugin", () => { it("splits by space and returns first word", { timeout: 5000 }, () => { expect(engine().parse("{name:[0]}", { name: "John Doe" })).toBe("John"); }); it("splits by @ and returns domain", { timeout: 5000 }, () => { expect( engine().parse("{email:@[1]}", { email: "user@example.com" }) ).toBe("example.com"); }); it("splits by comma and returns second element", { timeout: 5000 }, () => { expect(engine().parse("{tags:,[1]}", { tags: "foo,bar,baz" })).toBe( "bar" ); }); it("supports negative index", { timeout: 5000 }, () => { expect(engine().parse("{path:/[-1]}", { path: "/a/b/c" })).toBe("c"); }); it("returns empty for out-of-range index", { timeout: 5000 }, () => { expect(engine().parse("{name:[5]}", { name: "hi" })).toBe(""); }); it("returns empty for out-of-range negative index", { timeout: 5000, }, () => { expect(engine().parse("{name:[-5]}", { name: "hi" })).toBe(""); }); it("returns empty for undefined path", { timeout: 5000 }, () => { expect(engine().parse("{missing:[0]}", {})).toBe(""); }); it("skips _ prefixed variables", { timeout: 5000 }, () => { expect(engine().parse("{_foo:[0]}", {})).toBe("{_foo:[0]}"); }); it("returns SKIP_PLUGIN when path or indexStr missing (defensive guard)", { timeout: 5000, }, () => { const plugin = createStringSplitPlugin(); const state = createParseState(); // groups[1] undefined → !path guard const matchNoPath = { match: "{:[0]}", groups: Object.assign(["{:[0]}", undefined, "", "0"], { index: 0, input: "", }) as RegExpMatchArray, index: 0, }; expect(plugin.transform(matchNoPath, {}, state)).toBe(SKIP_PLUGIN); }); it("returns SKIP_PLUGIN for _ prefixed path (direct transform)", { timeout: 5000, }, () => { const plugin = createStringSplitPlugin(); const state = createParseState(); const matchUnder = { match: "{_foo:[0]}", groups: Object.assign(["{_foo:[0]}", "_foo", "", "0"], { index: 0, input: "", }) as RegExpMatchArray, index: 0, }; expect(plugin.transform(matchUnder, {}, state)).toBe(SKIP_PLUGIN); }); it("parts[actual] element is always a string — ?? '' is a type guard", { timeout: 5000, }, () => { // String.split always returns strings; verify normal path returns correctly expect(engine().parse("{val:,[0]}", { val: "a,b" })).toBe("a"); }); });