60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { sanitizeRconOutput, validateRconCommand, validateRconConnection } from "./rcon-validation";
|
|
|
|
describe("RCON validation", () => {
|
|
it("normalizes any valid DNS hostname and port without deployment configuration", () => {
|
|
expect(validateRconConnection({
|
|
name: " Season 4 ",
|
|
host: "SEASON4.SOMC.SVC.CLUSTER.LOCAL",
|
|
port: "25575",
|
|
password: "correct horse battery staple",
|
|
}, { passwordRequired: true })).toEqual({
|
|
name: "Season 4",
|
|
host: "season4.somc.svc.cluster.local",
|
|
port: 25575,
|
|
password: "correct horse battery staple",
|
|
});
|
|
|
|
expect(validateRconConnection({
|
|
name: "Creative",
|
|
host: "creative.example.net",
|
|
port: "43210",
|
|
password: "secret",
|
|
}, { passwordRequired: true })).toEqual({
|
|
name: "Creative",
|
|
host: "creative.example.net",
|
|
port: 43210,
|
|
password: "secret",
|
|
});
|
|
});
|
|
|
|
it("rejects IP literals and malformed DNS hostnames", () => {
|
|
for (const host of ["10.0.0.1", "2001:db8::1", "season4.", "-season4.example", "season4..example"]) {
|
|
expect(validateRconConnection({ name: "Server", host, port: "25575", password: "secret" }, {
|
|
passwordRequired: true,
|
|
})).toBeNull();
|
|
}
|
|
});
|
|
|
|
it("allows a blank replacement password only while editing", () => {
|
|
expect(validateRconConnection({ name: "Server", host: "season4.somc.svc.cluster.local", port: "25575", password: "" }, {
|
|
passwordRequired: false,
|
|
})?.password).toBeNull();
|
|
expect(validateRconConnection({ name: "Server", host: "season4.somc.svc.cluster.local", port: "25575", password: "" }, {
|
|
passwordRequired: true,
|
|
})).toBeNull();
|
|
});
|
|
|
|
it("bounds commands by UTF-8 bytes and rejects control characters", () => {
|
|
expect(validateRconCommand(" list ")).toBe("list");
|
|
expect(validateRconCommand("say first\nsay second")).toBeNull();
|
|
expect(validateRconCommand("say \u001b[31mred")).toBeNull();
|
|
expect(validateRconCommand(`say ${"😀".repeat(300)}`)).toBeNull();
|
|
});
|
|
|
|
it("strips output controls and bounds output by UTF-8 bytes", () => {
|
|
expect(sanitizeRconOutput("ok\u001b[31mred\u0000done")).toBe("ok[31mreddone");
|
|
expect(Buffer.byteLength(sanitizeRconOutput("😀".repeat(20_000)), "utf8")).toBeLessThanOrEqual(65_536);
|
|
});
|
|
});
|