Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / lib / password / memorable.spec.ts
bloba7ba2233aabe63ec4d1c9719983494dca2ce9a89
1 import { SeperatorOptions, digitChars, specialChars } from './constants';
2 import type { MemorablePasswordOptions } from './memorable';
3 import { generateMemorablePassword } from './memorable';
4 import WORD_LIST from './wordlist.json';
6 const WORDS = Object.values(WORD_LIST);
8 const wordsInList = (words: string[], options: MemorablePasswordOptions) =>
9     words.every((word) => {
10         let originalWord = word.toLowerCase();
11         if (options.extraNumbers) originalWord = originalWord.slice(0, -1);
12         return WORDS.includes(originalWord);
13     });
15 const wordsMatchCapitalization = (words: string[], options: MemorablePasswordOptions) =>
16     words.every((word) => (options.capitalize ? /[A-Z]/.test(word[0]) : true));
18 const wordsMatchExtraNumbers = (words: string[], options: MemorablePasswordOptions) =>
19     words.every((word) => (options.extraNumbers ? /[0-9]/.test(word[word.length - 1]) : true));
21 describe('memorable password generator', () => {
22     test('should throw if wordCount is 0', () => {
23         expect(() =>
24             generateMemorablePassword({
25                 wordCount: 0,
26                 seperator: SeperatorOptions.HYPHEN,
27                 capitalize: false,
28                 extraNumbers: false,
29             })
30         ).toThrow();
31     });
33     test('generate from wordlist with basic seperators', () => {
34         const options: MemorablePasswordOptions[] = [
35             { wordCount: 1, seperator: SeperatorOptions.HYPHEN, capitalize: false, extraNumbers: false },
36             { wordCount: 4, seperator: SeperatorOptions.HYPHEN, capitalize: false, extraNumbers: false },
37             { wordCount: 4, seperator: SeperatorOptions.COMMA, capitalize: true, extraNumbers: false },
38             { wordCount: 4, seperator: SeperatorOptions.PERIOD, capitalize: false, extraNumbers: false },
39             { wordCount: 4, seperator: SeperatorOptions.UNDERSCORE, capitalize: false, extraNumbers: false },
40             { wordCount: 4, seperator: SeperatorOptions.SPACE, capitalize: false, extraNumbers: false },
41             { wordCount: 5, seperator: SeperatorOptions.HYPHEN, capitalize: true, extraNumbers: false },
42             { wordCount: 10, seperator: SeperatorOptions.SPACE, capitalize: false, extraNumbers: false },
43             { wordCount: 15, seperator: SeperatorOptions.UNDERSCORE, capitalize: true, extraNumbers: false },
44         ];
46         options.forEach((options) => {
47             const result = generateMemorablePassword(options);
48             const words = result.split(options.seperator);
49             expect(result).toBeDefined();
50             expect(words.length).toEqual(options.wordCount);
51             expect(wordsInList(words, options)).toBe(true);
52             expect(wordsMatchCapitalization(words, options)).toBe(true);
53             expect(wordsMatchExtraNumbers(words, options)).toBe(true);
54         });
55     });
57     test('generate from wordlist with random number seperator', () => {
58         const options: MemorablePasswordOptions[] = [
59             { wordCount: 4, seperator: SeperatorOptions.NUMBER, capitalize: false, extraNumbers: false },
60             { wordCount: 5, seperator: SeperatorOptions.NUMBER, capitalize: true, extraNumbers: false },
61             { wordCount: 10, seperator: SeperatorOptions.NUMBER, capitalize: true, extraNumbers: false },
62             { wordCount: 15, seperator: SeperatorOptions.NUMBER, capitalize: false, extraNumbers: false },
63         ];
65         options.forEach((options) => {
66             const result = generateMemorablePassword(options);
67             const words = result.split(new RegExp(digitChars.split('').join('|')));
68             expect(result).toBeDefined();
69             expect(words.length).toEqual(options.wordCount);
70             expect(wordsInList(words, options)).toBe(true);
71             expect(wordsMatchCapitalization(words, options)).toBe(true);
72             expect(wordsMatchExtraNumbers(words, options)).toBe(true);
73         });
74     });
76     test('generate from wordlist with random number or symbol seperator', () => {
77         const options: MemorablePasswordOptions[] = [
78             { wordCount: 4, seperator: SeperatorOptions.NUMBER_OR_SYMBOL, capitalize: false, extraNumbers: false },
79             { wordCount: 5, seperator: SeperatorOptions.NUMBER_OR_SYMBOL, capitalize: true, extraNumbers: false },
80             { wordCount: 10, seperator: SeperatorOptions.NUMBER_OR_SYMBOL, capitalize: true, extraNumbers: false },
81             { wordCount: 15, seperator: SeperatorOptions.NUMBER_OR_SYMBOL, capitalize: false, extraNumbers: false },
82         ];
84         options.forEach((options) => {
85             const result = generateMemorablePassword(options);
86             const words = result.split(
87                 new RegExp(
88                     digitChars
89                         .concat(specialChars)
90                         .split('')
91                         .map((char) => (specialChars.includes(char) ? `\\${char}` : char))
92                         .join('|')
93                 )
94             );
95             expect(result).toBeDefined();
96             expect(words.length).toEqual(options.wordCount);
97             expect(wordsInList(words, options)).toBe(true);
98             expect(wordsMatchCapitalization(words, options)).toBe(true);
99             expect(wordsMatchExtraNumbers(words, options)).toBe(true);
100         });
101     });
103     test('should support interpolating extra numbers', () => {
104         const options: MemorablePasswordOptions[] = [
105             { wordCount: 1, seperator: SeperatorOptions.HYPHEN, capitalize: false, extraNumbers: true },
106             { wordCount: 4, seperator: SeperatorOptions.HYPHEN, capitalize: false, extraNumbers: true },
107             { wordCount: 4, seperator: SeperatorOptions.COMMA, capitalize: true, extraNumbers: true },
108             { wordCount: 4, seperator: SeperatorOptions.PERIOD, capitalize: false, extraNumbers: true },
109             { wordCount: 4, seperator: SeperatorOptions.UNDERSCORE, capitalize: false, extraNumbers: true },
110             { wordCount: 4, seperator: SeperatorOptions.SPACE, capitalize: false, extraNumbers: true },
111             { wordCount: 5, seperator: SeperatorOptions.HYPHEN, capitalize: true, extraNumbers: true },
112             { wordCount: 10, seperator: SeperatorOptions.SPACE, capitalize: false, extraNumbers: true },
113             { wordCount: 15, seperator: SeperatorOptions.UNDERSCORE, capitalize: true, extraNumbers: true },
114         ];
116         options.forEach((options) => {
117             const result = generateMemorablePassword(options);
118             const words = result.split(options.seperator);
119             expect(result).toBeDefined();
120             expect(words.length).toEqual(options.wordCount);
121             expect(wordsInList(words, options)).toBe(true);
122             expect(wordsMatchCapitalization(words, options)).toBe(true);
123             expect(wordsMatchExtraNumbers(words, options)).toBe(true);
124         });
125     });