Skip to content

Commit 4dccb92

Browse files
authored
redo commit existing fxa test (#92)
* redo commit existing fxa test * increase timeout for ci * finish existing fxa test, fix new fxa test * typo * shorted wait * force sync if timeout * remove force sync, lengthen sync timeout * mark tests unstable * increase otp timeout again * wait for any otp field * increase wait for otp input * log out fxa * address pr review
1 parent 0e4dab9 commit 4dccb92

File tree

9 files changed

+171
-41
lines changed

9 files changed

+171
-41
lines changed

conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ def driver(
177177
separator = " "
178178
winsize = [int(s) for s in opt_window_size.split(separator)]
179179
driver.set_window_size(*winsize)
180-
driver.implicitly_wait(opt_implicit_timeout)
180+
timeout = 30 if opt_ci else opt_implicit_timeout
181+
driver.implicitly_wait(timeout)
181182
yield driver
182183

183184
finally:

modules/browser_object_panel_ui.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ def click_sync_sign_in_button(self) -> BasePage:
7575
self.select_panel_setting("fxa-sign-in")
7676
return self
7777

78+
def log_out_fxa(self) -> BasePage:
79+
"""
80+
Click FxA signout button.
81+
"""
82+
with self.driver.context(self.driver.CONTEXT_CHROME):
83+
self.click_sync_sign_in_button()
84+
self.get_element("fxa-sign-out-button").click()
85+
return self
86+
7887
def manage_fxa_account(self) -> BasePage:
7988
"""
8089
Open the FxA management flow.
@@ -90,5 +99,19 @@ def confirm_sync_in_progress(self) -> BasePage:
9099
"""
91100
with self.driver.context(self.driver.CONTEXT_CHROME):
92101
self.click_sync_sign_in_button()
93-
self.element_has_text("fxa-sync-label", "Syncing")
102+
self.custom_wait(timeout=30, poll_frequency=0.5).until(
103+
EC.text_to_be_present_in_element(
104+
self.get_selector("fxa-sync-label"), "Syncing"
105+
)
106+
)
107+
return self
108+
109+
def start_sync(self) -> BasePage:
110+
"""
111+
Start FxA sync
112+
"""
113+
with self.driver.context(self.driver.CONTEXT_CHROME):
114+
self.click_sync_sign_in_button()
115+
self.element_has_text("fxa-sync-label", "Sync now")
116+
self.get_element("fxa-sync-label").click()
94117
return self

modules/data/fxa_new_account.components.json renamed to modules/data/fxa_home.components.json

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"groups": [
66
"requiredForPage"
77
]
8+
89
},
910

1011
"submit-button": {
@@ -15,13 +16,13 @@
1516
]
1617
},
1718

18-
"password-input": {
19+
"signup-password-input": {
1920
"selectorData": "[data-testid='new-password-input-field']",
2021
"strategy": "css",
2122
"groups": []
2223
},
2324

24-
"password-repeat-input": {
25+
"signup-password-repeat-input": {
2526
"selectorData": "[data-testid='verify-password-input-field']",
2627
"strategy": "css",
2728
"groups": []
@@ -39,12 +40,24 @@
3940
"groups": []
4041
},
4142

42-
"otp-input": {
43+
"signup-otp-input": {
4344
"selectorData": "[data-testid='confirm-signup-code-input-field']",
4445
"strategy": "css",
4546
"groups": []
4647
},
4748

49+
"signin-otp-input": {
50+
"selectorData": "[data-testid='signin-token-code-input-field']",
51+
"strategy": "css",
52+
"groups": []
53+
},
54+
55+
"otp-input": {
56+
"selectorData": "input[inputmode='numeric']",
57+
"strategy": "css",
58+
"groups": []
59+
},
60+
4861
"connected-heading": {
4962
"selectorData": "fxa-connected-heading",
5063
"strategy": "id",
@@ -58,7 +71,7 @@
5871
},
5972

6073
"login-password-input": {
61-
"selectorData": "input#password",
74+
"selectorData": "input[type='password']",
6275
"strategy": "css",
6376
"groups": []
6477
},

modules/page_object.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from modules.page_object_autofill_credit_card import *
1111
from modules.page_object_autofill_test_basic import *
1212
from modules.page_object_example_page import *
13-
from modules.page_object_fxa_new_account import *
13+
from modules.page_object_fxa_home import *
1414
from modules.page_object_generics import *
1515
from modules.page_object_google_search import *
1616
from modules.page_object_wiki_firefox_logo import *

modules/page_object_fxa_new_account.py renamed to modules/page_object_fxa_home.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
from selenium.common.exceptions import NoSuchElementException, TimeoutException
2+
from selenium.webdriver.support import expected_conditions as EC
3+
14
from modules.page_base import BasePage
25

36

4-
class FxaNewAccount(BasePage):
5-
"""
6-
Page Object Model for FxA signup flow.
7-
Initialize with fxa_url=<the url of the FxA instance>
8-
"""
7+
class FxaHome(BasePage):
8+
"""Page Object Model for FxA pages"""
99

1010
URL_TEMPLATE = "{fxa_url}"
1111

@@ -15,16 +15,30 @@ def sign_up_sign_in(self, email: str) -> BasePage:
1515
self.get_element("submit-button").click()
1616
return self
1717

18+
def fill_password(self, password: str) -> BasePage:
19+
self.set_content_context()
20+
self.fill("login-password-input", password, press_enter=False)
21+
self.get_element("submit-button").click()
22+
# If OTP is needed, wait for the field to be ready, else move on.
23+
try:
24+
self.custom_wait(timeout=3).until(
25+
EC.presence_of_element_located(self.get_selector("connected-heading"))
26+
)
27+
except (TimeoutException, NoSuchElementException):
28+
self.element_exists("otp-input")
29+
return self
30+
1831
def create_new_account(self, password: str, age=30) -> BasePage:
1932
"""Fill out the password and age fields, then submit and wait for code"""
20-
self.fill("password-input", password, press_enter=False)
21-
self.fill("password-repeat-input", password, press_enter=False)
33+
self.fill("signup-password-input", password, press_enter=False)
34+
self.fill("signup-password-repeat-input", password, press_enter=False)
2235
self.fill("age-input", str(age), press_enter=False)
36+
self.element_clickable("submit-button")
2337
self.get_element("submit-button").click()
2438
self.element_has_text("card-header", "Enter confirmation code")
2539
return self
2640

27-
def confirm_new_account(self, otp: str) -> BasePage:
41+
def fill_otp_code(self, otp: str) -> BasePage:
2842
"""Given an OTP, confirm the account, submit, and wait for account activation"""
2943
self.fill("otp-input", otp, press_enter=False)
3044
self.get_element("submit-button").click()

tests/address_bar_and_search/test_intervention_card_refresh_firefox.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def add_prefs():
1919
]
2020

2121

22+
@pytest.mark.unstable
2223
def test_intervention_card_refresh(driver: Firefox):
2324
"""
2425
C1365204.1: regular firefox, check the intervention card

tests/sync_and_fxa/conftest.py

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from datetime import datetime
23
from time import sleep
34

45
import pytest
@@ -7,6 +8,22 @@
78
from fxa.tests.utils import TestEmailAccount
89

910

11+
class FxaPrep:
12+
def __init__(self, url: str, password: str):
13+
self.client = Client(url)
14+
self.restmail = TestEmailAccount()
15+
self.password = password
16+
self.otp_code = None
17+
logging.info(self.restmail.email)
18+
logging.info(self.password)
19+
20+
def create_account(self):
21+
self.session = self.client.create_account(self.restmail.email, self.password)
22+
23+
def destroy_account(self):
24+
self.client.destroy_account(self.restmail.email, self.password)
25+
26+
1027
@pytest.fixture()
1128
def suite_id():
1229
return ("S2130", "Sync & Firefox Account")
@@ -16,6 +33,13 @@ def suite_id():
1633
def fxa_url(fxa_env):
1734
if fxa_env == "stage":
1835
return "https://accounts.stage.mozaws.net"
36+
elif fxa_env == "prod":
37+
return "https://accounts.firefox.com"
38+
39+
40+
@pytest.fixture()
41+
def start_time():
42+
return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
1943

2044

2145
@pytest.fixture()
@@ -25,39 +49,50 @@ def set_prefs(fxa_url):
2549

2650

2751
@pytest.fixture()
28-
def new_fxa_prep(fxa_url: str, acct_password: str) -> dict:
52+
def new_fxa_prep(fxa_url: str, acct_password: str) -> FxaPrep:
2953
"""Create a PyFxA object and return a dict with artifacts"""
3054
# Create a testing account using an @restmail.net address.
31-
acct = TestEmailAccount()
32-
client = Client(fxa_url)
33-
yield {
34-
"client": client,
35-
"restmail": acct,
36-
"password": acct_password,
37-
"otp_code": None,
38-
}
39-
acct.clear()
55+
prep = FxaPrep(fxa_url, acct_password)
56+
prep.restmail.clear()
57+
yield prep
4058
try:
41-
client.destroy_account(acct.email, acct_password)
59+
prep.destroy_account()
4260
except OutOfProtocolError as e:
4361
logging.info(repr(e))
4462

4563

4664
@pytest.fixture()
47-
def get_otp_code(new_fxa_prep):
65+
def restmail_session(fxa_test_account) -> TestEmailAccount:
66+
(username, _) = fxa_test_account
67+
return TestEmailAccount(email=username)
68+
69+
70+
@pytest.fixture()
71+
def create_fxa(new_fxa_prep: FxaPrep, get_otp_code) -> FxaPrep:
72+
"""Create FxA from a PyFxA object"""
73+
new_fxa_prep.create_account()
74+
new_fxa_prep.session.verify_email_code(get_otp_code())
75+
return new_fxa_prep
76+
77+
78+
@pytest.fixture()
79+
def get_otp_code(start_time: str):
4880
"""Function factory: wait for the OTP email, then return the OTP code"""
4981

50-
def _get_otp_code() -> str:
51-
acct = new_fxa_prep["restmail"]
82+
def _get_otp_code(restmail: TestEmailAccount) -> str:
83+
acct = restmail
84+
code_header_names = ["x-verify-short-code", "x-signin-verify-code"]
5285
logging.info("==========")
5386
for _ in range(60):
5487
acct.fetch()
5588
logging.info("---")
5689
for m in acct.messages:
57-
logging.info("Email headers")
58-
logging.info(m["headers"])
59-
if "x-verify-short-code" in m["headers"]:
60-
return m["headers"]["x-verify-short-code"]
90+
logging.info("Parsing email message...")
91+
if m["receivedAt"] < start_time:
92+
continue
93+
for header_name in code_header_names:
94+
if header_name in m["headers"]:
95+
return m["headers"][header_name]
6196
sleep(0.5)
6297
assert False, f"No OTP code found in {acct.email}."
6398

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logging
2+
from typing import Tuple
3+
4+
import pytest
5+
from selenium.common.exceptions import NoSuchElementException, TimeoutException
6+
from selenium.webdriver import Firefox
7+
from selenium.webdriver.support import expected_conditions as EC
8+
9+
from modules.browser_object import PanelUi
10+
from modules.page_object import FxaHome
11+
12+
13+
@pytest.fixture()
14+
def fxa_env():
15+
return "stage"
16+
17+
18+
@pytest.fixture()
19+
def fxa_test_account():
20+
return ("[email protected]", "Test123???")
21+
22+
23+
@pytest.mark.unstable
24+
def test_sync_existing_fxa(
25+
driver: Firefox, fxa_test_account: Tuple[str, str], restmail_session, get_otp_code
26+
):
27+
(username, password) = fxa_test_account
28+
panel_ui = PanelUi(driver)
29+
panel_ui.click_sync_sign_in_button()
30+
fxa = FxaHome(driver)
31+
fxa.sign_up_sign_in(username)
32+
fxa.fill_password(password)
33+
34+
try:
35+
fxa.custom_wait(timeout=15).until(
36+
EC.presence_of_element_located(fxa.get_selector("otp-input"))
37+
)
38+
otp = get_otp_code(restmail_session)
39+
logging.info(f"otp code: {otp}")
40+
fxa.fill_otp_code(otp)
41+
except (NoSuchElementException, TimeoutException):
42+
pass
43+
panel_ui.confirm_sync_in_progress()

tests/sync_and_fxa/test_new_fxa.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from selenium.webdriver import Firefox
33

44
from modules.browser_object import PanelUi
5-
from modules.page_object import FxaNewAccount, GenericPage
5+
from modules.page_object import FxaHome, GenericPage
66

77

88
@pytest.fixture()
@@ -25,17 +25,17 @@ def test_sync_new_fxa(driver: Firefox, fxa_url: str, new_fxa_prep: dict, get_otp
2525
page.url_contains(fxa_url)
2626

2727
# Walk through the FxA setup flow
28-
fxa = FxaNewAccount(driver)
29-
email = new_fxa_prep["restmail"].email
28+
fxa = FxaHome(driver)
29+
email = new_fxa_prep.restmail.email
3030
fxa.sign_up_sign_in(email)
31-
fxa.create_new_account(new_fxa_prep["password"])
32-
otp = get_otp_code()
33-
fxa.confirm_new_account(otp)
31+
fxa.create_new_account(new_fxa_prep.password)
32+
otp = get_otp_code(new_fxa_prep.restmail)
33+
fxa.fill_otp_code(otp)
3434
fxa.get_element("continue-browsing-link").click()
3535

3636
# Walk through the Finish Account Setup flow and confirm sync
3737
fxa.driver.get(fxa_url)
38-
fxa.get_element("sign-in-button").click()
38+
fxa.get_element("submit-button").click()
3939
panel_ui.manage_fxa_account()
40-
fxa.finish_account_setup(new_fxa_prep["password"])
40+
fxa.finish_account_setup(new_fxa_prep.password)
4141
panel_ui.confirm_sync_in_progress()

0 commit comments

Comments
 (0)