@@ -16,14 +16,45 @@ import { FirefoxCommand } from '../../lib/channels';
1616import { syncDesktopOAuthQueryParams } from '../../lib/query-params' ;
1717import { getCode } from 'fxa-settings/src/lib/totp' ;
1818
19+ const realTestPhoneNumber = process . env . RECOVERY_PHONE__TWILIO__TEST_NUMBER ;
20+
21+ function getPhoneNumber ( env : string ) {
22+ if ( env !== 'local' && realTestPhoneNumber ) {
23+ return realTestPhoneNumber ;
24+ }
25+ // See Twilio test credentials phone numbers: https://www.twilio.com/docs/iam/test-credentials
26+ return '4159929960' ;
27+ }
28+
1929test . describe ( 'severity-1 #smoke' , ( ) => {
2030 test . describe ( 'recovery phone' , ( ) => {
21- test . beforeEach ( async ( { pages : { configPage } } , { project } ) => {
31+ // Run these tests sequentially when using the Twilio API because they rely on the same test phone number.
32+ // When using the Twilio API, we cannot determine the order in which the messages were received.
33+ if ( realTestPhoneNumber ) {
34+ test . describe . configure ( { mode : 'serial' } ) ;
35+ } else {
36+ test . describe . configure ( { mode : 'parallel' } ) ;
37+ }
38+
39+ test . beforeEach ( async ( { pages : { configPage } , target } ) => {
2240 // Ensure that the feature flag is enabled
2341 const config = await configPage . getConfig ( ) ;
24- test . fixme ( project . name !== 'local' , 'FXA-11159' ) ;
2542 test . skip ( config . featureFlags . enableAdding2FABackupPhone !== true ) ;
2643 test . skip ( config . featureFlags . enableUsing2FABackupPhone !== true ) ;
44+
45+ // Twilio does not allow you to fetch messages when using test credentials.
46+ // Therefore, we fallback to peeking at Redis to get confirmation codes.
47+ if ( target . name === 'local' ) {
48+ expect (
49+ target . smsClient . isTwilioEnabled ( ) ,
50+ 'Local env found, use redis and Twilio test creds'
51+ ) . toBeFalsy ( ) ;
52+ } else {
53+ expect (
54+ target . smsClient . isTwilioEnabled ( ) ,
55+ 'Stage/Prod env, use Twilio API'
56+ ) . toBeTruthy ( ) ;
57+ }
2758 } ) ;
2859
2960 test ( 'setup fails with invalid number' , async ( {
@@ -68,12 +99,15 @@ test.describe('severity-1 #smoke', () => {
6899
69100 await expect ( recoveryPhone . addHeader ( ) ) . toBeVisible ( ) ;
70101
71- await recoveryPhone . enterPhoneNumber ( '4159929960' ) ;
102+ await recoveryPhone . enterPhoneNumber ( getPhoneNumber ( target . name ) ) ;
72103 await recoveryPhone . clickSendCode ( ) ;
73104
74105 await expect ( recoveryPhone . confirmHeader ) . toBeVisible ( ) ;
75106
76- const code = await target . smsClient . getCode ( credentials . uid ) ;
107+ const code = await target . smsClient . getCode (
108+ getPhoneNumber ( target . name ) ,
109+ credentials . uid
110+ ) ;
77111
78112 // Invalid code
79113 await recoveryPhone . enterCode ( '123456' ) ;
@@ -84,7 +118,10 @@ test.describe('severity-1 #smoke', () => {
84118
85119 // Sends a new code
86120 await recoveryPhone . clickResendCode ( ) ;
87- const nextCode = await target . smsClient . getCode ( credentials . uid ) ;
121+ const nextCode = await target . smsClient . getCode (
122+ getPhoneNumber ( target . name ) ,
123+ credentials . uid
124+ ) ;
88125
89126 expect ( code ) . not . toEqual ( nextCode ) ;
90127
@@ -332,13 +369,19 @@ test.describe('severity-1 #smoke', () => {
332369 page . getByText ( 'Invalid or expired confirmation code' )
333370 ) . toBeVisible ( ) ;
334371
335- const originalCode = await target . smsClient . getCode ( credentials . uid ) ;
372+ const originalCode = await target . smsClient . getCode (
373+ getPhoneNumber ( target . name ) ,
374+ credentials . uid
375+ ) ;
336376
337377 // Sends a new code
338378 await signinRecoveryPhone . clickResendCode ( ) ;
339379 await expect ( page . getByText ( 'Code sent' ) ) . toBeVisible ( ) ;
340380
341- const nextCode = await target . smsClient . getCode ( credentials . uid ) ;
381+ const nextCode = await target . smsClient . getCode (
382+ getPhoneNumber ( target . name ) ,
383+ credentials . uid
384+ ) ;
342385
343386 expect ( originalCode ) . not . toEqual ( nextCode ) ;
344387
@@ -590,14 +633,17 @@ async function setupRecoveryPhone({
590633
591634 await expect ( recoveryPhone . addHeader ( ) ) . toBeVisible ( ) ;
592635
593- await recoveryPhone . enterPhoneNumber ( '4159929960' ) ;
636+ await recoveryPhone . enterPhoneNumber ( getPhoneNumber ( target . name ) ) ;
594637 await recoveryPhone . clickSendCode ( ) ;
595638
596639 await expect ( recoveryPhone . confirmHeader ) . toBeVisible ( ) ;
597640
598- const registerCode = await target . smsClient . getCode ( credentials . uid ) ;
641+ const code = await target . smsClient . getCode (
642+ getPhoneNumber ( target . name ) ,
643+ credentials . uid
644+ ) ;
599645
600- await recoveryPhone . enterCode ( registerCode ) ;
646+ await recoveryPhone . enterCode ( code ) ;
601647 await recoveryPhone . clickConfirm ( ) ;
602648
603649 await page . waitForURL ( / s e t t i n g s / ) ;
@@ -645,13 +691,19 @@ async function fillOutRecoveryPhoneFromEmailFirst({
645691 page . getByText ( 'Invalid or expired confirmation code' )
646692 ) . toBeVisible ( ) ;
647693
648- const originalCode = await target . smsClient . getCode ( credentials . uid ) ;
694+ const originalCode = await target . smsClient . getCode (
695+ getPhoneNumber ( target . name ) ,
696+ credentials . uid
697+ ) ;
649698
650699 // Sends a new code
651700 await signinRecoveryPhone . clickResendCode ( ) ;
652701 await expect ( page . getByText ( 'Code sent' ) ) . toBeVisible ( ) ;
653702
654- const nextCode = await target . smsClient . getCode ( credentials . uid ) ;
703+ const nextCode = await target . smsClient . getCode (
704+ getPhoneNumber ( target . name ) ,
705+ credentials . uid
706+ ) ;
655707
656708 expect ( originalCode ) . not . toEqual ( nextCode ) ;
657709
0 commit comments