|
9 | 9 | fapiUrl, |
10 | 10 | holdRequests, |
11 | 11 | serveFapi, |
| 12 | + VERIFICATION_CODE, |
12 | 13 | worker, |
13 | 14 | } from '../../../../__tests__/feature/fake-fapi'; |
14 | 15 | import { fapiClient, fapiPhoneNumber, fapiSession, fapiUser } from '../../../../__tests__/feature/fapi'; |
@@ -370,9 +371,10 @@ describe('User profile MFA management', () => { |
370 | 371 | } |
371 | 372 | expect(screen.getByRole('button', { name: 'Copy and close' })).toBeVisible(); |
372 | 373 | expect(screen.getByRole('button', { name: 'Copy and close' })).toHaveAttribute('aria-disabled', 'true'); |
373 | | - await waitFor(() => expect(screen.getByRole('button', { name: 'Close' })).toHaveFocus()); |
| 374 | + expect(screen.queryByRole('button', { name: 'Close' })).toBeNull(); |
374 | 375 | held.release(); |
375 | 376 | await waitFor(() => expect(screen.getByText('CODE0100')).toBeVisible()); |
| 377 | + expect(screen.getByRole('button', { name: 'Close' })).toBeVisible(); |
376 | 378 | for (const name of ['Print', 'Download', 'Copy and close']) { |
377 | 379 | expect(screen.getByRole('button', { name })).toBeEnabled(); |
378 | 380 | } |
@@ -481,9 +483,13 @@ describe('User profile MFA management', () => { |
481 | 483 | await regenerate(user); |
482 | 484 | await waitFor(() => expect(first.requests).toHaveLength(1)); |
483 | 485 | const dialog = screen.getByRole('dialog'); |
484 | | - await user.keyboard('{Escape}'); |
485 | | - expect(dialog).toBeVisible(); |
486 | | - first.release(); |
| 486 | + try { |
| 487 | + expect(within(dialog).queryByRole('button', { name: 'Close' })).toBeNull(); |
| 488 | + await user.keyboard('{Escape}'); |
| 489 | + expect(dialog).toBeVisible(); |
| 490 | + } finally { |
| 491 | + first.release(); |
| 492 | + } |
487 | 493 |
|
488 | 494 | expect(await within(dialog).findByText('Enter your current password to continue')).toBeVisible(); |
489 | 495 | await user.type(screen.getByLabelText('Password'), 'hunter2{Enter}'); |
@@ -511,6 +517,37 @@ describe('User profile MFA management', () => { |
511 | 517 | expect(fapi.mfa.phoneUpdates).toContainEqual({ id: 'phone_1', reserved: true, default: undefined }); |
512 | 518 | }); |
513 | 519 |
|
| 520 | + it('keeps SMS code verification open until its reservation challenge can be cancelled', async () => { |
| 521 | + const unverified = fapiPhoneNumber({ ...phone, verification: { ...phone.verification, status: 'unverified' } }); |
| 522 | + const fapi = await renderMfa(fapiUser({ id: 'user_1', phone_numbers: [unverified] }), mfaEnvironment(), { |
| 523 | + verification: { secrets: { password: 'hunter2' } }, |
| 524 | + }); |
| 525 | + demandReverificationOnce('/v1/me/phone_numbers/phone_1'); |
| 526 | + const user = userEvent.setup(); |
| 527 | + |
| 528 | + await startSms(user); |
| 529 | + await user.click(screen.getByRole('button', { name: 'Continue' })); |
| 530 | + const code = await screen.findByRole('textbox', { name: 'Verification code' }); |
| 531 | + const attempt = holdRequests('post', '/v1/me/phone_numbers/phone_1/attempt_verification'); |
| 532 | + await user.type(code, VERIFICATION_CODE); |
| 533 | + await waitFor(() => expect(attempt.requests).toHaveLength(1)); |
| 534 | + const dialog = screen.getByRole('dialog'); |
| 535 | + try { |
| 536 | + expect(within(dialog).queryByRole('button', { name: 'Close' })).toBeNull(); |
| 537 | + await user.keyboard('{Escape}'); |
| 538 | + expect(dialog).toBeVisible(); |
| 539 | + } finally { |
| 540 | + attempt.release(); |
| 541 | + } |
| 542 | + |
| 543 | + expect(await within(dialog).findByText('Enter your current password to continue')).toBeVisible(); |
| 544 | + await user.click(within(dialog).getByRole('button', { name: 'Close' })); |
| 545 | + await waitFor(() => expect(screen.queryByRole('dialog')).toBeNull()); |
| 546 | + expect(fapi.mfa.phoneAttempts).toEqual([{ id: 'phone_1', code: VERIFICATION_CODE }]); |
| 547 | + expect(fapi.mfa.phoneUpdates).toEqual([]); |
| 548 | + expect(screen.queryByRole('alert')).toBeNull(); |
| 549 | + }); |
| 550 | + |
514 | 551 | it('verifies the session before creating a phone for SMS MFA, then sends its code', async () => { |
515 | 552 | const fapi = await renderMfa(fapiUser({ id: 'user_1' }), mfaEnvironment(), { |
516 | 553 | verification: { secrets: { password: 'hunter2' } }, |
|
0 commit comments