import assert from "node:assert/strict";
import { test } from "node:test";
import {
createRoomSchema,
joinRoomSchema,
roomGuessSchema,
chatMessageSchema,
} from "../shared/multiplayer";
const map = "00000000-0000-4000-8000-000000000000";
test("chat accepts plain multilingual text and rejects blank, oversized or hidden-control messages", () => {
assert.equal(
chatMessageSchema.parse({ clientId: map, text: " Привет (: " }).text,
"Привет (:",
);
assert.equal(
chatMessageSchema.safeParse({ clientId: map, text: "x".repeat(500) })
.success,
true,
);
for (const text of [
"",
" ",
"x".repeat(501),
"hidden\u202e",
"hidden\u0085",
"x\nname",
"x\u0000name",
])
assert.equal(
chatMessageSchema.safeParse({ clientId: map, text }).success,
false,
);
assert.equal(
chatMessageSchema.safeParse({ clientId: "wrong", text: "hi" }).success,
false,
);
assert.equal(
chatMessageSchema.parse({
clientId: map,
text: "",
}).text,
"",
);
});
test("room limits include the owner and stay between 2 and 16", () => {
for (const playerLimit of [2, 16])
assert.equal(
createRoomSchema.parse({
datasetId: map,
difficulty: "normal",
displayName: " Alex ",
playerLimit,
}).displayName,
"Alex",
);
for (const playerLimit of [1, 17, 2.5, "16", null])
assert.equal(
createRoomSchema.safeParse({
datasetId: map,
difficulty: "normal",
displayName: "Alex",
playerLimit,
}).success,
false,
);
});
test("multiplayer names and guesses reject hidden controls, invalid rounds, and non-finite positions", () => {
assert.equal(
joinRoomSchema.parse({ displayName: " Друг " }).displayName,
"Друг",
);
for (const displayName of ["a", "x\nname", "name\u202e", "a".repeat(33)])
assert.equal(joinRoomSchema.safeParse({ displayName }).success, false);
for (const payload of [
{ round: 5, x: 0, z: 0 },
{ round: 0, x: Infinity, z: 0 },
{ round: 0, x: NaN, z: 0 },
{ round: 0, x: 0 },
])
assert.equal(roomGuessSchema.safeParse(payload).success, false);
});