1import { describe, expect, it } from "vitest";
2
3import {
4 loginInputSchema,
5 passwordSchema,
6 passwordResetConfirmSchema,
7 passwordResetRequestSchema,
8 registerInputSchema,
9 updateProfileInputSchema,
10} from "./auth.dto.js";
11
12describe("password policy", () => {
13 it("accepts a valid password", () => {
14 expect(passwordSchema.safeParse("hunter222222").success).toBe(true);
15 expect(passwordSchema.safeParse("a1".padEnd(10, "x")).success).toBe(true);
16 });
17
18 it("rejects too-short passwords", () => {
19 const r = passwordSchema.safeParse("a12345678");
20 expect(r.success).toBe(false);
21 });
22
23 it("rejects password without a letter", () => {
24 expect(passwordSchema.safeParse("1234567890").success).toBe(false);
25 });
26
27 it("rejects password without a number", () => {
28 expect(passwordSchema.safeParse("abcdefghijkl").success).toBe(false);
29 });
30
31 it("rejects empty and >72 char passwords", () => {
32 expect(passwordSchema.safeParse("").success).toBe(false);
33 expect(passwordSchema.safeParse("a1" + "x".repeat(71)).success).toBe(false);
34 });
35
36 it("uppercase letters count as letters", () => {
37 expect(passwordSchema.safeParse("Password123").success).toBe(true);
38 });
39});
40
41describe("registerInputSchema", () => {
42 it("accepts a valid register payload", () => {
43 const r = registerInputSchema.safeParse({
44 name: "Ada Lovelace",
45 email: "Ada@Example.com",
46 password: "Password123",
47 });
48 expect(r.success).toBe(true);
49 if (r.success) expect(r.data.email).toBe("ada@example.com");
50 });
51
52 it("rejects invalid email", () => {
53 expect(
54 registerInputSchema.safeParse({ name: "A", email: "not-an-email", password: "Password123" })
55 .success,
56 ).toBe(false);
57 });
58
59 it("rejects weak password", () => {
60 expect(
61 registerInputSchema.safeParse({ name: "A", email: "a@b.co", password: "short" }).success,
62 ).toBe(false);
63 });
64
65 it("rejects unknown fields (strict)", () => {
66 expect(
67 registerInputSchema.safeParse({
68 name: "A",
69 email: "a@b.co",
70 password: "Password123",
71 hacker: true,
72 }).success,
73 ).toBe(false);
74 });
75
76 it("rejects empty name", () => {
77 expect(
78 registerInputSchema.safeParse({ name: "", email: "a@b.co", password: "Password123" }).success,
79 ).toBe(false);
80 });
81});
82
83describe("loginInputSchema", () => {
84 it("accepts email+password", () => {
85 expect(loginInputSchema.safeParse({ email: "a@b.co", password: "x" }).success).toBe(true);
86 });
87
88 it("rejects missing password", () => {
89 expect(loginInputSchema.safeParse({ email: "a@b.co" }).success).toBe(false);
90 });
91});
92
93describe("password reset", () => {
94 it("request: email only", () => {
95 expect(passwordResetRequestSchema.safeParse({ email: "a@b.co" }).success).toBe(true);
96 expect(passwordResetRequestSchema.safeParse({ email: "nope" }).success).toBe(false);
97 });
98
99 it("confirm: token + strong password", () => {
100 expect(
101 passwordResetConfirmSchema.safeParse({ token: "tok", password: "Password123" }).success,
102 ).toBe(true);
103 expect(passwordResetConfirmSchema.safeParse({ token: "tok", password: "weak" }).success).toBe(
104 false,
105 );
106 expect(passwordResetConfirmSchema.safeParse({ password: "Password123" }).success).toBe(false);
107 });
108});
109
110describe("updateProfileInputSchema", () => {
111 it("accepts a partial update", () => {
112 expect(updateProfileInputSchema.safeParse({ name: "Grace" }).success).toBe(true);
113 });
114
115 it("rejects empty object", () => {
116 expect(updateProfileInputSchema.safeParse({}).success).toBe(false);
117 });
118
119 it("validates theme enum", () => {
120 expect(updateProfileInputSchema.safeParse({ theme: "neon" }).success).toBe(false);
121 expect(updateProfileInputSchema.safeParse({ theme: "dark" }).success).toBe(true);
122 });
123});
124