Files
web/packages/common/utils/zod/passwordValidator.test.ts
Joakim Jäderberg daf765f3d5 Merged in feature/wrap-logging (pull request #2511)
Feature/wrap logging

* feat: change all logging to go through our own logger function so that we can control log levels

* move packages/trpc to using our own logger

* merge


Approved-by: Linus Flood
2025-07-03 12:37:04 +00:00

97 lines
4.0 KiB
TypeScript

import { beforeEach, describe, expect, test } from "vitest"
import { passwordValidator } from "./passwordValidator"
// Test cases to find differences between Curity and Zod validation
const testCases = [
// Valid passwords
{ password: "Password123!", description: "standard valid password" },
{ password: "ValidPass1@", description: "valid with @" },
// Edge cases for length
{ password: "Pass123!", description: "8 characters (too short for both)" },
{ password: "ValidPass1!", description: "10 characters (minimum)" },
{ password: "A".repeat(40) + "1!", description: "40 characters (maximum)" },
{ password: "A".repeat(41) + "1!", description: "41 characters (too long)" },
// Special character differences
{ password: "Password123*", description: "with asterisk" },
{ password: "Password123-", description: "with hyphen" },
{ password: "Password123=", description: "with equals" },
{ password: "Password123+", description: "with plus" },
{ password: "Password123_", description: "with underscore" },
{ password: "Password123&", description: "with ampersand" },
{ password: "Password123?", description: "with question mark" },
{ password: "Password123(", description: "with opening parenthesis" },
{ password: "Password123)", description: "with closing parenthesis" },
// International characters (Curity supports these, Zod might not)
{ password: "Påssword123!", description: "with å" },
{ password: "Pässword123!", description: "with ä" },
{ password: "Pöössword123!", description: "with ö" },
{ password: "Pæssword123!", description: "with æ" },
{ password: "Pøssword123!", description: "with ø" },
{ password: "Püssword123!", description: "with ü" },
{ password: "Paßsword123!", description: "with ß" },
// Mixed case international
{ password: "PÅSSWORD123!", description: "with uppercase Å" },
{ password: "PÄSSWORD123!", description: "with uppercase Ä" },
{ password: "PÖÖSSWORD123!", description: "with uppercase Ö" },
// Special characters not in Curity regex
{ password: "Password123~", description: "with tilde (not in Curity)" },
{ password: "Password123`", description: "with backtick (not in Curity)" },
{ password: "Password123|", description: "with pipe (not in Curity)" },
{ password: "Password123\\", description: "with backslash (not in Curity)" },
{
password: "Password123/",
description: "with forward slash (not in Curity)",
},
{ password: "Password123<", description: "with less than (not in Curity)" },
{
password: "Password123>",
description: "with greater than (not in Curity)",
},
{ password: "Password123.", description: "with period (not in Curity)" },
{ password: "Password123,", description: "with comma (not in Curity)" },
{ password: "Password123;", description: "with semicolon (not in Curity)" },
{ password: "Password123:", description: "with colon (not in Curity)" },
{ password: "Password123'", description: "with apostrophe (not in Curity)" },
{ password: 'Password123"', description: "with quote (not in Curity)" },
{
password: "Password123[",
description: "with opening bracket (not in Curity)",
},
{
password: "Password123]",
description: "with closing bracket (not in Curity)",
},
{
password: "Password123{",
description: "with opening brace (not in Curity)",
},
{
password: "Password123}",
description: "with closing brace (not in Curity)",
},
]
const curityPasswordRegex = new RegExp(
"^(?!^.{41})(?=.{10,})(?=.*[0-9])(?=.*[a-zåäöæøüß])(?=.*[A-ZÅÄÖÆØÜ])(?=.*[&!?()@#$%^+=_\*\-])[A-Za-zåäöæøüßÅÄÖÆØÜ0-9&!?()@#$%^+=_\*\-]+$",
"g"
)
describe("Should validate password the same way as Curity", () => {
beforeEach(() => {
// reset regex state before test
curityPasswordRegex.lastIndex = 0
})
test.each(testCases)("$description", ({ password }) => {
const curityResult = curityPasswordRegex.test(password)
const zodResult = passwordValidator().safeParse(password)
expect(zodResult.success).toBe(curityResult)
})
})