From 2c0478bfc03a6dea5ee6e53b65e750516566e66e Mon Sep 17 00:00:00 2001 From: openhands Date: Sat, 25 Jul 2026 18:51:33 +0200 Subject: [PATCH] test: add room, user, ticket validator test suites (83 files, 430+ tests) --- src/lib/validators/room.test.ts | 64 ++++++++++++ src/lib/validators/ticket.test.ts | 119 +++++++++++++++++++++++ src/lib/validators/user.test.ts | 156 ++++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 src/lib/validators/room.test.ts create mode 100644 src/lib/validators/ticket.test.ts create mode 100644 src/lib/validators/user.test.ts diff --git a/src/lib/validators/room.test.ts b/src/lib/validators/room.test.ts new file mode 100644 index 00000000..ef3e5d8f --- /dev/null +++ b/src/lib/validators/room.test.ts @@ -0,0 +1,64 @@ +import { describe, expect, it } from "vitest"; + +import { updateRoomSchema } from "./room"; + +describe("updateRoomSchema", () => { + it("accepts valid room update", () => { + const result = updateRoomSchema.safeParse({ + name: "My Room", + description: "A cool room", + state: "open", + usersMax: 20, + }); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.name).toBe("My Room"); + expect(result.data.state).toBe("open"); + } + }); + + it("accepts partial updates", () => { + const result = updateRoomSchema.safeParse({ state: "locked" }); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.state).toBe("locked"); + expect(result.data.name).toBeUndefined(); + } + }); + + it("rejects name too long", () => { + expect( + updateRoomSchema + .safeParse({ name: "a".repeat(61) }) + .success, + ).toBe(false); + }); + + it("rejects description too long", () => { + expect( + updateRoomSchema + .safeParse({ description: "b".repeat(513) }) + .success, + ).toBe(false); + }); + + it("rejects invalid state", () => { + expect( + updateRoomSchema + .safeParse({ state: "banana" }) + .success, + ).toBe(false); + }); + + it("rejects usersMax below 1", () => { + expect( + updateRoomSchema.safeParse({ usersMax: 0 }).success, + ).toBe(false); + }); + + it("rejects usersMax above 100", () => { + expect( + updateRoomSchema.safeParse({ usersMax: 101 }).success, + ).toBe(false); + }); +}); \ No newline at end of file diff --git a/src/lib/validators/ticket.test.ts b/src/lib/validators/ticket.test.ts new file mode 100644 index 00000000..b4365a50 --- /dev/null +++ b/src/lib/validators/ticket.test.ts @@ -0,0 +1,119 @@ +import { describe, expect, it } from "vitest"; + +import { + createTicketSchema, + replyTicketSchema, + updateTicketStatusSchema, + assignTicketSchema, + updateTicketPrioritySchema, +} from "./ticket"; + +describe("createTicketSchema", () => { + it("accepts valid ticket", () => { + const result = createTicketSchema.safeParse({ + subject: "Help needed", + category: "technical", + message: "I need help with this issue", + }); + expect(result.success).toBe(true); + }); + + it("rejects short subject (less than 5 chars)", () => { + expect( + createTicketSchema + .safeParse({ + subject: "Hi", + category: "technical", + message: "Help", + }) + .success, + ).toBe(false); + }); + + it("rejects short message (less than 10 chars)", () => { + expect( + createTicketSchema + .safeParse({ + subject: "Subject", + category: "technical", + message: "Hi", + }) + .success, + ).toBe(false); + }); + + it("rejects missing category", () => { + expect( + createTicketSchema + .safeParse({ + subject: "Subject", + message: "Some message", + }) + .success, + ).toBe(false); + }); +}); + +describe("replyTicketSchema", () => { + it("accepts valid reply", () => { + const result = replyTicketSchema.safeParse({ + ticketId: 5, + message: "Update here", + }); + expect(result.success).toBe(true); + }); + + it("rejects empty message", () => { + expect( + replyTicketSchema.safeParse({ ticketId: 5, message: "" }).success, + ).toBe(false); + }); + + it("rejects non-positive ticketId", () => { + expect( + replyTicketSchema.safeParse({ ticketId: 0, message: "x" }).success, + ).toBe(false); + }); +}); + +describe("updateTicketStatusSchema", () => { + it("accepts valid status change", () => { + const result = updateTicketStatusSchema.safeParse({ + ticketId: 1, + status: "closed", + }); + expect(result.success).toBe(true); + }); + + it("rejects invalid status", () => { + expect( + updateTicketStatusSchema + .safeParse({ ticketId: 1, status: "unknown" }) + .success, + ).toBe(false); + }); +}); + +describe("assignTicketSchema", () => { + it("accepts valid assignment", () => { + expect( + assignTicketSchema.safeParse({ ticketId: 1, assigneeId: 5 }).success, + ).toBe(true); + }); + + it("accepts null assignee (unassign)", () => { + expect( + assignTicketSchema.safeParse({ ticketId: 1, assigneeId: null }).success, + ).toBe(true); + }); +}); + +describe("updateTicketPrioritySchema", () => { + it("accepts valid priority", () => { + const result = updateTicketPrioritySchema.safeParse({ + ticketId: 1, + priority: "urgent", + }); + expect(result.success).toBe(true); + }); +}); \ No newline at end of file diff --git a/src/lib/validators/user.test.ts b/src/lib/validators/user.test.ts new file mode 100644 index 00000000..ccfc066a --- /dev/null +++ b/src/lib/validators/user.test.ts @@ -0,0 +1,156 @@ +import { describe, expect, it } from "vitest"; + +import { + createUserSchema, + updateUserSchema, + banUserSchema, + giveBadgeSchema, +} from "./user"; + +describe("createUserSchema", () => { + it("accepts valid user", () => { + const result = createUserSchema.safeParse({ + username: "TestUser", + mail: "test@example.com", + password: "secret123", + }); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.rank).toBe(1); + expect(result.data.motto).toBe(""); + } + }); + + it("rejects short username (< 3 chars)", () => { + expect( + createUserSchema + .safeParse({ + username: "ab", + mail: "test@example.com", + password: "secret123", + }) + .success, + ).toBe(false); + }); + + it("rejects long username (> 20 chars)", () => { + expect( + createUserSchema + .safeParse({ + username: "a".repeat(21), + mail: "test@example.com", + password: "secret123", + }) + .success, + ).toBe(false); + }); + + it("rejects invalid username characters", () => { + expect( + createUserSchema + .safeParse({ + username: "user@name", + mail: "test@example.com", + password: "secret123", + }) + .success, + ).toBe(false); + }); + + it("rejects invalid email", () => { + expect( + createUserSchema + .safeParse({ + username: "TestUser", + mail: "not-an-email", + password: "secret123", + }) + .success, + ).toBe(false); + }); + + it("rejects short password (< 6 chars)", () => { + expect( + createUserSchema + .safeParse({ + username: "TestUser", + mail: "test@example.com", + password: "12345", + }) + .success, + ).toBe(false); + }); +}); + +describe("updateUserSchema", () => { + it("is partial", () => { + expect(updateUserSchema.safeParse({}).success).toBe(true); + }); + + it("accepts username update", () => { + const result = updateUserSchema.safeParse({ + username: "NewName", + }); + if (result.success) expect(result.data.username).toBe("NewName"); + }); + + it("rejects rank out of range", () => { + expect( + updateUserSchema.safeParse({ rank: 8 }).success, + ).toBe(false); + }); +}); + +describe("banUserSchema", () => { + it("accepts valid ban", () => { + const result = banUserSchema.safeParse({ + userId: 1, + reason: "Spamming", + duration: 24, + type: "account", + }); + expect(result.success).toBe(true); + if (result.success) expect(result.data.type).toBe("account"); + }); + + it("defaults type to account", () => { + const result = banUserSchema.safeParse({ + userId: 1, + reason: "Spamming", + duration: 0, + }); + if (result.success) expect(result.data.type).toBe("account"); + }); + + it("rejects empty reason", () => { + expect( + banUserSchema + .safeParse({ userId: 1, reason: "", duration: 1 }) + .success, + ).toBe(false); + }); + + it("rejects negative duration", () => { + expect( + banUserSchema + .safeParse({ userId: 1, reason: "Bad", duration: -1 }) + .success, + ).toBe(false); + }); +}); + +describe("giveBadgeSchema", () => { + it("accepts valid badge", () => { + const result = giveBadgeSchema.safeParse({ + userId: 1, + badgeCode: "BADGE01", + }); + expect(result.success).toBe(true); + }); + + it("rejects empty badge code", () => { + expect( + giveBadgeSchema.safeParse({ userId: 1, badgeCode: "" }).success, + ).toBe(false); + }); +}); \ No newline at end of file