1 import { specialChars } from './constants';
2 import type { RandomPasswordOptions } from './random';
3 import { generateRandomPassword } from './random';
5 const passwordMatchesOptions = (password: string, options: RandomPasswordOptions) => {
6 const validLength = password.length === options.length;
7 const validUppercase = !options.useUppercase || /[A-Z]/.test(password);
8 const validDigits = !options.useDigits || /[0-9]/.test(password);
9 const validSpecialChars =
10 !options.useSpecialChars ||
14 .map((char) => (specialChars.includes(char) ? `\\${char}` : char))
18 return validLength && validUppercase && validDigits && validSpecialChars;
21 describe('random password generator', () => {
22 test('should throw if password length is smaller than 4', () => {
24 generateRandomPassword({
27 useSpecialChars: true,
33 generateRandomPassword({
36 useSpecialChars: true,
42 test('supports lowercase mode', () => {
43 const options: RandomPasswordOptions[] = [
44 { length: 4, useDigits: false, useSpecialChars: false, useUppercase: false },
45 { length: 5, useDigits: false, useSpecialChars: false, useUppercase: false },
46 { length: 10, useDigits: false, useSpecialChars: false, useUppercase: false },
47 { length: 15, useDigits: false, useSpecialChars: false, useUppercase: false },
48 { length: 20, useDigits: false, useSpecialChars: false, useUppercase: false },
51 options.forEach((option) => expect(passwordMatchesOptions(generateRandomPassword(option), option)).toBe(true));
54 test('supports uppercase mode', () => {
55 const options: RandomPasswordOptions[] = [
56 { length: 4, useDigits: false, useSpecialChars: false, useUppercase: true },
57 { length: 5, useDigits: false, useSpecialChars: false, useUppercase: true },
58 { length: 10, useDigits: false, useSpecialChars: false, useUppercase: true },
59 { length: 15, useDigits: false, useSpecialChars: false, useUppercase: true },
60 { length: 20, useDigits: false, useSpecialChars: false, useUppercase: true },
63 options.forEach((option) => expect(passwordMatchesOptions(generateRandomPassword(option), option)).toBe(true));
66 test('supports digits mode', () => {
67 const options: RandomPasswordOptions[] = [
68 { length: 4, useDigits: true, useSpecialChars: false, useUppercase: false },
69 { length: 5, useDigits: true, useSpecialChars: false, useUppercase: false },
70 { length: 10, useDigits: true, useSpecialChars: false, useUppercase: false },
71 { length: 15, useDigits: true, useSpecialChars: false, useUppercase: false },
72 { length: 20, useDigits: true, useSpecialChars: false, useUppercase: false },
75 options.forEach((option) => expect(passwordMatchesOptions(generateRandomPassword(option), option)).toBe(true));
78 test('supports special mode', () => {
79 const options: RandomPasswordOptions[] = [
80 { length: 4, useDigits: false, useSpecialChars: true, useUppercase: false },
81 { length: 5, useDigits: false, useSpecialChars: true, useUppercase: false },
82 { length: 10, useDigits: false, useSpecialChars: true, useUppercase: false },
83 { length: 15, useDigits: false, useSpecialChars: true, useUppercase: false },
84 { length: 20, useDigits: false, useSpecialChars: true, useUppercase: false },
87 options.forEach((option) => expect(passwordMatchesOptions(generateRandomPassword(option), option)).toBe(true));
90 test('supports combinations', () => {
91 const options: RandomPasswordOptions[] = [
92 { length: 4, useDigits: true, useSpecialChars: true, useUppercase: true },
93 { length: 5, useDigits: false, useSpecialChars: true, useUppercase: true },
94 { length: 10, useDigits: true, useSpecialChars: false, useUppercase: true },
95 { length: 15, useDigits: true, useSpecialChars: true, useUppercase: false },
96 { length: 20, useDigits: true, useSpecialChars: true, useUppercase: true },
99 options.forEach((option) => expect(passwordMatchesOptions(generateRandomPassword(option), option)).toBe(true));
102 test('password validation recursion sanity check', () => {
103 const options: RandomPasswordOptions[] = Array.from({ length: 1000 }, () => ({
106 useSpecialChars: true,
110 options.forEach((option) => {
112 generateRandomPassword(option, () => counter++);
113 expect(counter).toBeLessThan(100);