Files
suaveplan/packages/foundation/data/templates/src/plugins/transform/StringSplitPlugin.test.ts
2026-05-27 23:47:53 +01:00

90 lines
3.1 KiB
TypeScript

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");
});
});