1 import getSentinelRecoveryProps from './getSentinelRecoveryProps';
4 setRecoveryPhrase: 'Set recovery phrase',
5 setRecoveryEmail: 'Add a recovery email address',
6 setRecoveryPhone: 'Add a recovery phone number',
7 disableRecoveryEmail: 'Disable recovery by email address',
8 disableRecoveryPhone: 'Disable recovery by phone number',
9 verifyRecoveryEmail: 'Verify email address',
10 verifyRecoveryPhone: 'Verify phone number',
11 statusTextSuccess: 'Your account recovery method is set',
12 statusTextDanger: 'No account recovery method set; you are at risk of losing access to your account',
13 statusTextWarningInsecure: 'To ensure continuous access to your account, set an account recovery method',
14 statusTextWarning: 'To ensure highest possible security of your account',
17 const mockIds = { data: 'someData', account: `someAccount` };
21 SET: 'test@proton.com',
22 PHONESET: '555555555',
29 const emailOutcomes = [
31 description: 'email unset/unverified/disabled',
33 Value: OUTCOMES.UNSET,
34 Status: OUTCOMES.UNVERIFIED,
36 Reset: OUTCOMES.DISABLED,
40 description: 'email set/unverified/disabled',
43 Status: OUTCOMES.UNVERIFIED,
45 Reset: OUTCOMES.DISABLED,
49 description: 'email set/unverified/enabled',
52 Status: OUTCOMES.UNVERIFIED,
54 Reset: OUTCOMES.ENABLED,
58 description: 'email set/verified/disabled',
61 Status: OUTCOMES.VERIFIED,
63 Reset: OUTCOMES.DISABLED,
67 description: 'email set/verified/enabled',
70 Status: OUTCOMES.VERIFIED,
72 Reset: OUTCOMES.ENABLED,
77 const phoneOutcomes = [
79 description: 'phone unset/unverified/disabled',
81 Value: OUTCOMES.UNSET,
82 Status: OUTCOMES.UNVERIFIED,
84 Reset: OUTCOMES.DISABLED,
88 description: 'phone set/unverified/disabled',
90 Value: OUTCOMES.PHONESET,
91 Status: OUTCOMES.UNVERIFIED,
93 Reset: OUTCOMES.DISABLED,
97 description: 'phone set/unverified/enabled',
99 Value: OUTCOMES.PHONESET,
100 Status: OUTCOMES.UNVERIFIED,
102 Reset: OUTCOMES.ENABLED,
106 description: 'phone set/verified/disabled',
108 Value: OUTCOMES.PHONESET,
109 Status: OUTCOMES.VERIFIED,
111 Reset: OUTCOMES.DISABLED,
115 description: 'phone set/verified/enabled',
117 Value: OUTCOMES.PHONESET,
118 Status: OUTCOMES.VERIFIED,
120 Reset: OUTCOMES.ENABLED,
125 const casesWithoutMnemonic = {
129 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[0].description}`,
130 email: emailOutcomes[0].case,
131 phone: phoneOutcomes[0].case,
132 expected: [text.setRecoveryPhrase, text.setRecoveryEmail, text.setRecoveryPhone],
135 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[1].description}`,
136 email: emailOutcomes[0].case,
137 phone: phoneOutcomes[1].case,
138 expected: [text.setRecoveryPhrase, text.setRecoveryEmail, text.verifyRecoveryPhone],
141 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[0].description}`,
142 email: emailOutcomes[1].case,
143 phone: phoneOutcomes[0].case,
144 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.setRecoveryPhone],
147 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[1].description}`,
148 email: emailOutcomes[1].case,
149 phone: phoneOutcomes[1].case,
150 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.verifyRecoveryPhone],
155 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[0].description}`,
156 email: emailOutcomes[3].case,
157 phone: phoneOutcomes[0].case,
158 expected: [text.setRecoveryPhrase, text.setRecoveryPhone],
161 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[1].description}`,
162 email: emailOutcomes[3].case,
163 phone: phoneOutcomes[1].case,
164 expected: [text.setRecoveryPhrase, text.verifyRecoveryPhone],
167 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[3].description}`,
168 email: emailOutcomes[0].case,
169 phone: phoneOutcomes[3].case,
170 expected: [text.setRecoveryPhrase, text.setRecoveryEmail],
173 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[3].description}`,
174 email: emailOutcomes[1].case,
175 phone: phoneOutcomes[3].case,
176 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail],
181 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[3].description}`,
182 email: emailOutcomes[3].case,
183 phone: phoneOutcomes[3].case,
184 expected: [text.setRecoveryPhrase],
191 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[2].description}`,
192 email: emailOutcomes[0].case,
193 phone: phoneOutcomes[2].case,
194 expected: [text.setRecoveryPhrase, text.setRecoveryEmail, text.verifyRecoveryPhone],
197 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[2].description}`,
198 email: emailOutcomes[1].case,
199 phone: phoneOutcomes[2].case,
200 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.verifyRecoveryPhone],
203 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[0].description}`,
204 email: emailOutcomes[2].case,
205 phone: phoneOutcomes[0].case,
206 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.setRecoveryPhone],
209 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[1].description}`,
210 email: emailOutcomes[2].case,
211 phone: phoneOutcomes[1].case,
212 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.verifyRecoveryPhone],
215 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[2].description}`,
216 email: emailOutcomes[2].case,
217 phone: phoneOutcomes[2].case,
218 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail, text.verifyRecoveryPhone],
223 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[2].description}`,
224 email: emailOutcomes[3].case,
225 phone: phoneOutcomes[2].case,
226 expected: [text.setRecoveryPhrase, text.verifyRecoveryPhone],
229 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[3].description}`,
230 email: emailOutcomes[2].case,
231 phone: phoneOutcomes[3].case,
232 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail],
237 twoActionsEmailSVE: [
239 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[0].description}`,
240 email: emailOutcomes[4].case,
241 phone: phoneOutcomes[0].case,
242 expected: [text.setRecoveryPhrase, text.setRecoveryPhone],
245 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[1].description}`,
246 email: emailOutcomes[4].case,
247 phone: phoneOutcomes[1].case,
248 expected: [text.setRecoveryPhrase, text.verifyRecoveryPhone],
251 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[2].description}`,
252 email: emailOutcomes[4].case,
253 phone: phoneOutcomes[2].case,
254 expected: [text.setRecoveryPhrase, text.verifyRecoveryPhone],
257 twoActionsPhoneSVE: [
259 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[4].description}`,
260 email: emailOutcomes[0].case,
261 phone: phoneOutcomes[4].case,
262 expected: [text.setRecoveryPhrase, text.setRecoveryEmail],
265 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[4].description}`,
266 email: emailOutcomes[1].case,
267 phone: phoneOutcomes[4].case,
268 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail],
271 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[4].description}`,
272 email: emailOutcomes[2].case,
273 phone: phoneOutcomes[4].case,
274 expected: [text.setRecoveryPhrase, text.verifyRecoveryEmail],
277 oneActionBothSVEorSVD: [
279 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[4].description}`,
280 email: emailOutcomes[3].case,
281 phone: phoneOutcomes[4].case,
282 expected: [text.setRecoveryPhrase],
285 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[3].description}`,
286 email: emailOutcomes[4].case,
287 phone: phoneOutcomes[3].case,
288 expected: [text.setRecoveryPhrase],
291 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[4].description}`,
292 email: emailOutcomes[4].case,
293 phone: phoneOutcomes[4].case,
294 expected: [text.setRecoveryPhrase],
300 const casesWithMnemonic = {
303 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[3].description}`,
304 email: emailOutcomes[3].case,
305 phone: phoneOutcomes[3].case,
309 emailOrPhoneSentinelConfigured: [
311 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[0].description}`,
312 email: emailOutcomes[3].case,
313 phone: phoneOutcomes[0].case,
314 expected: [text.setRecoveryPhone],
317 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[1].description}`,
318 email: emailOutcomes[3].case,
319 phone: phoneOutcomes[1].case,
320 expected: [text.verifyRecoveryPhone],
323 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[2].description}`,
324 email: emailOutcomes[3].case,
325 phone: phoneOutcomes[2].case,
326 expected: [text.disableRecoveryPhone],
329 desc: `${emailOutcomes[3].description} and ${phoneOutcomes[4].description}`,
330 email: emailOutcomes[3].case,
331 phone: phoneOutcomes[4].case,
332 expected: [text.disableRecoveryPhone],
335 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[3].description}`,
336 email: emailOutcomes[0].case,
337 phone: phoneOutcomes[3].case,
338 expected: [text.setRecoveryEmail],
341 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[3].description}`,
342 email: emailOutcomes[1].case,
343 phone: phoneOutcomes[3].case,
344 expected: [text.verifyRecoveryEmail],
347 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[3].description}`,
348 email: emailOutcomes[2].case,
349 phone: phoneOutcomes[3].case,
350 expected: [text.disableRecoveryEmail],
353 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[3].description}`,
354 email: emailOutcomes[4].case,
355 phone: phoneOutcomes[3].case,
356 expected: [text.disableRecoveryEmail],
359 emailNotSetUnverifiedDisabled: [
361 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[0].description}`,
362 email: emailOutcomes[0].case,
363 phone: phoneOutcomes[0].case,
364 expected: [text.setRecoveryEmail, text.setRecoveryPhone],
367 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[1].description}`,
368 email: emailOutcomes[0].case,
369 phone: phoneOutcomes[1].case,
370 expected: [text.setRecoveryEmail, text.verifyRecoveryPhone],
373 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[2].description}`,
374 email: emailOutcomes[0].case,
375 phone: phoneOutcomes[2].case,
376 expected: [text.disableRecoveryPhone, text.setRecoveryEmail],
379 desc: `${emailOutcomes[0].description} and ${phoneOutcomes[4].description}`,
380 email: emailOutcomes[0].case,
381 phone: phoneOutcomes[4].case,
382 expected: [text.disableRecoveryPhone, text.setRecoveryEmail],
385 emailSetUnverifiedDisabled: [
387 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[0].description}`,
388 email: emailOutcomes[1].case,
389 phone: phoneOutcomes[0].case,
390 expected: [text.verifyRecoveryEmail, text.setRecoveryPhone],
393 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[1].description}`,
394 email: emailOutcomes[1].case,
395 phone: phoneOutcomes[1].case,
396 expected: [text.verifyRecoveryEmail, text.verifyRecoveryPhone],
399 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[2].description}`,
400 email: emailOutcomes[1].case,
401 phone: phoneOutcomes[2].case,
402 expected: [text.disableRecoveryPhone, text.verifyRecoveryEmail],
405 desc: `${emailOutcomes[1].description} and ${phoneOutcomes[4].description}`,
406 email: emailOutcomes[1].case,
407 phone: phoneOutcomes[4].case,
408 expected: [text.disableRecoveryPhone, text.verifyRecoveryEmail],
411 emailSetUnverifiedEnabled: [
413 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[0].description}`,
414 email: emailOutcomes[2].case,
415 phone: phoneOutcomes[0].case,
416 expected: [text.disableRecoveryEmail, text.setRecoveryPhone],
419 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[1].description}`,
420 email: emailOutcomes[2].case,
421 phone: phoneOutcomes[1].case,
422 expected: [text.disableRecoveryEmail, text.verifyRecoveryPhone],
425 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[2].description}`,
426 email: emailOutcomes[2].case,
427 phone: phoneOutcomes[2].case,
428 expected: [text.disableRecoveryEmail, text.disableRecoveryPhone],
431 desc: `${emailOutcomes[2].description} and ${phoneOutcomes[4].description}`,
432 email: emailOutcomes[2].case,
433 phone: phoneOutcomes[4].case,
434 expected: [text.disableRecoveryEmail, text.disableRecoveryPhone],
437 emailSetVerifiedEnabled: [
439 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[0].description}`,
440 email: emailOutcomes[4].case,
441 phone: phoneOutcomes[0].case,
442 expected: [text.disableRecoveryEmail, text.setRecoveryPhone],
445 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[1].description}`,
446 email: emailOutcomes[4].case,
447 phone: phoneOutcomes[1].case,
448 expected: [text.disableRecoveryEmail, text.verifyRecoveryPhone],
451 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[2].description}`,
452 email: emailOutcomes[4].case,
453 phone: phoneOutcomes[2].case,
454 expected: [text.disableRecoveryEmail, text.disableRecoveryPhone],
457 desc: `${emailOutcomes[4].description} and ${phoneOutcomes[4].description}`,
458 email: emailOutcomes[4].case,
459 phone: phoneOutcomes[4].case,
460 expected: [text.disableRecoveryEmail, text.disableRecoveryPhone],
465 const executeTest = (
480 expected: string[] | [];
482 hasMnemonic: boolean,
483 expectedStatusText: string,
484 expectedCTALength: number
486 test.each(cases)(`$desc`, ({ email, phone, expected }) => {
487 const result = getSentinelRecoveryProps(email, phone, hasMnemonic, mockIds);
488 const callToActions = result.callToActions ?? [];
490 expect(result.statusText).toBe(expectedStatusText);
491 expect(callToActions.length).toBe(expectedCTALength);
493 callToActions.forEach((action, index) => {
494 expect(action.text).toBe(expected[index]);
499 describe('getSentinelRecoveryProps returns status text "No account recovery..." when user does not have a recovery phrase', () => {
500 const expectedStatusText = text.statusTextDanger;
502 describe('returns 3 actions in the correct order', () => {
503 const expectedCTALength = 3;
504 executeTest(casesWithoutMnemonic.noAccountRecovery.threeActions, false, expectedStatusText, expectedCTALength);
507 describe('returns 2 actions in the correct order', () => {
508 const expectedCTALength = 2;
509 executeTest(casesWithoutMnemonic.noAccountRecovery.twoActions, false, expectedStatusText, expectedCTALength);
512 describe('returns 1 action', () => {
513 const expectedCTALength = 1;
514 executeTest(casesWithoutMnemonic.noAccountRecovery.oneAction, false, expectedStatusText, expectedCTALength);
518 describe('getSentinelRecoveryProps returns status text "To ensure continuous access..." when user does not have a recovery phrase', () => {
519 const expectedStatusText = text.statusTextWarningInsecure;
521 describe('returns 3 actions in the correct order', () => {
522 const expectedCTALength = 3;
523 executeTest(casesWithoutMnemonic.continuousAccess.threeActions, false, expectedStatusText, expectedCTALength);
526 describe('returns 2 actions in the correct order', () => {
527 const expectedCTALength = 2;
528 executeTest(casesWithoutMnemonic.continuousAccess.twoActions, false, expectedStatusText, expectedCTALength);
532 describe('getSentinelRecoveryProps returns status text "To ensure highest possible security..." when user does not have a recovery phrase', () => {
533 const expectedStatusText = text.statusTextWarning;
535 describe('returns 2 actions in the correct order when email is set/verified/enabled', () => {
536 const expectedCTALength = 2;
538 casesWithoutMnemonic.highestSecurity.twoActionsEmailSVE,
545 describe('returns 2 actions in the correct order when phone is set/verified/enabled', () => {
546 const expectedCTALength = 2;
548 casesWithoutMnemonic.highestSecurity.twoActionsPhoneSVE,
555 describe('returns 1 action when both are either set/verified/enabled or set/verified/disabled or both set/verified/enabled', () => {
556 const expectedCTALength = 1;
558 casesWithoutMnemonic.highestSecurity.oneActionBothSVEorSVD,
566 describe('getSentinelRecoveryProps returns status text "Your account recovery is set" when user has a recovery phrase and both email/phone sentinel configured', () => {
567 const expectedStatusText = text.statusTextSuccess;
568 const expectedCTALength = 0;
570 executeTest(casesWithMnemonic.bestCase, true, expectedStatusText, expectedCTALength);
573 describe('getSentinelRecoveryProps returns status text "To ensure highest possible security..." when user has a recovery phrase and email OR phone sentinel configured', () => {
574 const expectedStatusText = text.statusTextWarning;
575 const expectedCTALength = 1;
577 describe('returns 1 action', () => {
578 executeTest(casesWithMnemonic.emailOrPhoneSentinelConfigured, true, expectedStatusText, expectedCTALength);
582 describe('getSentinelRecoveryProps returns status text "To ensure highest possible security..." when user has a recovery phrase', () => {
583 const expectedStatusText = text.statusTextWarning;
584 const expectedCTALength = 2;
586 describe('returns 2 actions in the correct order when email is unset/unverified/disabled', () => {
587 executeTest(casesWithMnemonic.emailNotSetUnverifiedDisabled, true, expectedStatusText, expectedCTALength);
590 describe('returns 2 actions in the correct order when email is set/unverified/disabled', () => {
591 executeTest(casesWithMnemonic.emailSetUnverifiedDisabled, true, expectedStatusText, expectedCTALength);
594 describe('returns 2 actions in the correct order when email is set/unverified/enabled', () => {
595 executeTest(casesWithMnemonic.emailSetUnverifiedEnabled, true, expectedStatusText, expectedCTALength);
598 describe('returns 2 actions in the correct order when email is set/verified/enabled', () => {
599 executeTest(casesWithMnemonic.emailSetVerifiedEnabled, true, expectedStatusText, expectedCTALength);