90 lines
3.1 KiB
TypeScript
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");
|
|
});
|
|
});
|