Files

67 lines
2.7 KiB
TypeScript
Raw Permalink Normal View History

import { describe, expect, it } from "@jest/globals";
2026-06-09 12:34:30 -07:00
import { editUserBodyValidation } from "../../../src/api/validation/userValidation.ts";
const validPassword = "OldPass1!";
const validNewPassword = "NewPass1!";
describe("editUserBodyValidation", () => {
// Regression: the Joi->Zod validation refactor (commit c3a41272a3) dropped
// `password`/`newPassword` from this schema. Because z.object() strips
// unknown keys, the change-password flow in userService.editUser silently
// became a no-op. Both fields must survive parsing.
it("retains password and newPassword on the parsed body", () => {
const result = editUserBodyValidation.safeParse({
password: validPassword,
newPassword: validNewPassword,
});
expect(result.success).toBe(true);
expect(result.data).toEqual({
password: validPassword,
newPassword: validNewPassword,
});
});
it("accepts a profile-only edit with neither password field", () => {
const result = editUserBodyValidation.safeParse({ firstName: "Ada", lastName: "Lovelace" });
expect(result.success).toBe(true);
});
it("rejects password without newPassword", () => {
const result = editUserBodyValidation.safeParse({ password: validPassword });
expect(result.success).toBe(false);
});
it("rejects newPassword without password", () => {
const result = editUserBodyValidation.safeParse({ newPassword: validNewPassword });
expect(result.success).toBe(false);
});
it("rejects a newPassword that does not meet the strength policy", () => {
const result = editUserBodyValidation.safeParse({
password: validPassword,
newPassword: "weak",
});
expect(result.success).toBe(false);
});
2026-07-22 10:05:36 -07:00
// Regression: `deleteProfileImage` was missing from this schema, so z.object()
// stripped it before it reached the repository and the remove-profile-image
// flow was silently a no-op. The flag arrives as the multipart form-data
// string "true", so it must both survive parsing and coerce to a boolean.
it("retains deleteProfileImage and coerces the multipart string 'true' to boolean true", () => {
const result = editUserBodyValidation.safeParse({ deleteProfileImage: "true" });
expect(result.success).toBe(true);
expect(result.data).toEqual({ deleteProfileImage: true });
});
it("coerces the multipart string 'false' to boolean false", () => {
const result = editUserBodyValidation.safeParse({ deleteProfileImage: "false" });
expect(result.success).toBe(true);
expect(result.data).toEqual({ deleteProfileImage: false });
});
it("rejects a non-boolean deleteProfileImage value", () => {
const result = editUserBodyValidation.safeParse({ deleteProfileImage: "banana" });
expect(result.success).toBe(false);
});
});