test: dedupe repeated validation and throw assertions

This commit is contained in:
Peter Steinberger
2026-02-21 23:21:35 +00:00
parent 01ec832f78
commit 98790339ef
4 changed files with 49 additions and 26 deletions

View File

@@ -142,8 +142,8 @@ describe("resolveConfigIncludes", () => {
for (const testCase of cases) {
const files = { [configPath(testCase.includeFile)]: testCase.included };
const obj = { $include: `./${testCase.includeFile}`, extra: true };
expect(() => resolve(obj, files), testCase.includeFile).toThrow(ConfigIncludeError);
expect(() => resolve(obj, files), testCase.includeFile).toThrow(
expectResolveIncludeError(
() => resolve(obj, files),
/Sibling keys require included content to be an object/,
);
}

View File

@@ -21,10 +21,10 @@ import type { SessionEntry } from "./types.js";
describe("session path safety", () => {
it("rejects unsafe session IDs", () => {
expect(() => validateSessionId("../etc/passwd")).toThrow(/Invalid session ID/);
expect(() => validateSessionId("a/b")).toThrow(/Invalid session ID/);
expect(() => validateSessionId("a\\b")).toThrow(/Invalid session ID/);
expect(() => validateSessionId("/abs")).toThrow(/Invalid session ID/);
const unsafeSessionIds = ["../etc/passwd", "a/b", "a\\b", "/abs"];
for (const sessionId of unsafeSessionIds) {
expect(() => validateSessionId(sessionId), sessionId).toThrow(/Invalid session ID/);
}
});
it("resolves transcript path inside an explicit sessions dir", () => {

View File

@@ -333,9 +333,16 @@ describe("buildGatewayConnectionDetails", () => {
resolveGatewayPort.mockReturnValue(18789);
pickPrimaryTailnetIPv4.mockReturnValue(undefined);
expect(() => buildGatewayConnectionDetails()).toThrow("SECURITY ERROR");
expect(() => buildGatewayConnectionDetails()).toThrow("plaintext ws://");
expect(() => buildGatewayConnectionDetails()).toThrow("wss://");
let thrown: unknown;
try {
buildGatewayConnectionDetails();
} catch (error) {
thrown = error;
}
expect(thrown).toBeInstanceOf(Error);
expect((thrown as Error).message).toContain("SECURITY ERROR");
expect((thrown as Error).message).toContain("plaintext ws://");
expect((thrown as Error).message).toContain("wss://");
});
it("allows ws:// for loopback addresses in local mode", () => {

View File

@@ -19,23 +19,39 @@ describe("parseSlackBlocksInput", () => {
expect(parsed).toEqual([{ type: "section", text: { type: "mrkdwn", text: "hi" } }]);
});
it("rejects invalid JSON", () => {
expect(() => parseSlackBlocksInput("{bad-json")).toThrow(/valid JSON/i);
});
it("rejects invalid block payloads", () => {
const cases = [
{
name: "invalid JSON",
input: "{bad-json",
expectedMessage: /valid JSON/i,
},
{
name: "non-array payload",
input: { type: "divider" },
expectedMessage: /must be an array/i,
},
{
name: "empty array",
input: [],
expectedMessage: /at least one block/i,
},
{
name: "non-object block",
input: ["not-a-block"],
expectedMessage: /must be an object/i,
},
{
name: "missing block type",
input: [{}],
expectedMessage: /non-empty string type/i,
},
] as const;
it("rejects non-array payloads", () => {
expect(() => parseSlackBlocksInput({ type: "divider" })).toThrow(/must be an array/i);
});
it("rejects empty arrays", () => {
expect(() => parseSlackBlocksInput([])).toThrow(/at least one block/i);
});
it("rejects non-object blocks", () => {
expect(() => parseSlackBlocksInput(["not-a-block"])).toThrow(/must be an object/i);
});
it("rejects blocks without type", () => {
expect(() => parseSlackBlocksInput([{}])).toThrow(/non-empty string type/i);
for (const testCase of cases) {
expect(() => parseSlackBlocksInput(testCase.input), testCase.name).toThrow(
testCase.expectedMessage,
);
}
});
});