|
1 |
| -import sys, os |
2 |
| - |
3 |
| -base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) |
4 |
| -sys.path.insert(0, base_path) |
5 |
| - |
6 |
| -from playwright.sync_api import sync_playwright, expect |
7 |
| -import re, time |
8 | 1 | import imaplib
|
9 | 2 | import email
|
10 |
| -import random |
11 |
| -import string |
12 |
| - |
13 |
| -NEWDOT_URL = "https://dev.new.expensify.com:8082/" |
14 |
| - |
15 |
| -PASSWORD = "vjycqezohxxrdhzr" |
16 |
| - |
17 |
| - |
18 |
| -def new_dot_login(page, email): |
19 |
| - page.goto(NEWDOT_URL) |
20 |
| - page.locator('input[type="email"]').fill(email) |
21 |
| - page.wait_for_timeout(2000) |
22 |
| - page.get_by_role("button", name="Continue").nth(0).click() |
23 |
| - page.wait_for_timeout(10000) |
24 |
| - page.locator('input[data-testid="validateCode"]').fill("123456") |
25 |
| - |
26 |
| - |
27 |
| -def zip_error(page, assertion_errors): |
28 |
| - |
29 |
| - try: |
30 |
| - page.get_by_label("My settings").click() |
31 |
| - page.wait_for_timeout(1000) |
32 |
| - page.get_by_label("England's Lane, London,").click() |
33 |
| - page.wait_for_timeout(1000) |
34 |
| - page.get_by_label("Address line 1").get_by_role("textbox").fill("Maliebaan 87") |
35 |
| - page.wait_for_timeout(1000) |
36 |
| - page.get_by_text("Maliebaan").first.click() |
37 |
| - page.wait_for_timeout(1000) |
38 |
| - page.get_by_role("textbox", name="Zip / Postcode").fill("1012 JS") |
39 |
| - page.wait_for_timeout(1000) |
40 |
| - page.get_by_role("button", name="Save").click() |
41 |
| - page.wait_for_timeout(1000) |
42 |
| - expect(page.get_by_text("Incorrect zip code format.")).not_to_be_visible() |
43 |
| - except AssertionError as e: |
44 |
| - assertion_errors.append(f"Error: Zip code validation failed for 'Maliebaan 87': {str(e)}") |
45 |
| - |
46 |
| - try: |
47 |
| - page.get_by_label("87 Maliebaan, Utrecht,").click() |
48 |
| - page.wait_for_timeout(1000) |
49 |
| - page.get_by_label("Address line 1").get_by_role("textbox").fill("tokyo") |
50 |
| - page.wait_for_timeout(1000) |
51 |
| - page.get_by_text("Tokyo Metro Marunouchi Line").click() |
52 |
| - page.wait_for_timeout(1000) |
53 |
| - page.get_by_role("textbox", name="Zip / Postcode").fill("100-0001") |
54 |
| - page.wait_for_timeout(1000) |
55 |
| - page.get_by_role("button", name="Save").click() |
56 |
| - page.wait_for_timeout(1000) |
57 |
| - expect(page.get_by_text("Incorrect zip code format.")).not_to_be_visible() |
58 |
| - except AssertionError as e: |
59 |
| - assertion_errors.append(f"Error: Zip code validation failed for 'Tokyo Metro Marunouchi Line': {str(e)}") |
60 |
| - |
61 |
| - try: |
62 |
| - page.get_by_label("Tokyo Metro Marunouchi Line,").click() |
63 |
| - page.wait_for_timeout(1000) |
64 |
| - page.get_by_label("Address line 1").get_by_role("textbox").fill("engla") |
65 |
| - page.wait_for_timeout(1000) |
66 |
| - page.get_by_text("England's Lane").click() |
67 |
| - page.wait_for_timeout(1000) |
68 |
| - page.get_by_role("textbox", name="Zip / Postcode").fill("SW1A 1AA") |
69 |
| - page.wait_for_timeout(1000) |
70 |
| - page.get_by_role("button", name="Save").click() |
71 |
| - page.wait_for_timeout(1000) |
72 |
| - expect(page.get_by_text("Incorrect zip code format.")).not_to_be_visible() |
73 |
| - except AssertionError as e: |
74 |
| - assertion_errors.append(f"Error: Zip code validation failed for 'SW1A 1AA': {str(e)}") |
75 |
| - |
76 |
| - try: |
77 |
| - page.get_by_label("England's Lane, London,").click() |
78 |
| - page.get_by_role("textbox", name="Zip / Postcode").fill(",") |
79 |
| - page.wait_for_timeout(1000) |
80 |
| - page.get_by_role("button", name="Save").click() |
81 |
| - page.wait_for_timeout(1000) |
82 |
| - expect(page.get_by_text("Incorrect zip code format.")).to_be_visible() |
83 |
| - except AssertionError as e: |
84 |
| - assertion_errors.append(f"Error: Zip code validation failed for ',': {str(e)}") |
85 |
| - |
86 |
| - try: |
87 |
| - page.get_by_label("Back").click() |
88 |
| - page.get_by_label("England's Lane, London,").click() |
89 |
| - page.wait_for_timeout(1000) |
90 |
| - page.get_by_label("Address line 1").get_by_role("textbox").click() |
91 |
| - page.get_by_label("Address line 1").get_by_role("textbox").fill("2574 Fairfield Road") |
92 |
| - page.wait_for_timeout(1000) |
93 |
| - page.get_by_text("Fairfield Road").first.click() |
94 |
| - page.wait_for_timeout(1000) |
95 |
| - page.get_by_role("textbox", name="Zip / Postcode").fill("234GEs") |
96 |
| - page.wait_for_timeout(1000) |
97 |
| - page.get_by_role("button", name="Save").click() |
98 |
| - page.wait_for_timeout(1000) |
99 |
| - expect(page.get_by_text("Incorrect zip code format.")).to_be_visible() |
100 |
| - except AssertionError as e: |
101 |
| - assertion_errors.append(f"Error: Zip code validation failed for 'England's Lane, London': {str(e)}") |
102 |
| - |
103 |
| - |
104 |
| -def test_expensify_0000(): |
105 |
| - assertion_errors = [] # List to store assertion errors |
| 3 | +import re |
| 4 | +from email.header import decode_header |
| 5 | +from playwright.sync_api import sync_playwright, expect |
106 | 6 |
|
107 |
| - with sync_playwright() as p: |
108 |
| - browser = p.chromium.launch(proxy = {"server": "http://localhost:8080"}, headless = False, args = ["--no-sandbox", "--disable-dev-shm-usage", "--ignore-certificate-errors", "--disable-web-security", "--disable-features=IsolateOrigins,site-per-process"], slow_mo = None, channel = "chromium") |
109 |
| - first_user_context = browser.new_context(ignore_https_errors=True) |
110 |
| - page = first_user_context.new_page() |
111 |
| - page.wait_for_timeout(2000) |
| 7 | +# Enter Gmail credentials for a disposable |
| 8 | +GMAIL_NAME = "nomandevtur+55827.2" |
| 9 | +GMAIL_APP_PASSWORD = "tpye xlsj axyq nltq" |
112 | 10 |
|
113 | 11 |
|
114 |
| - new_dot_login( page, "[email protected]") |
| 12 | +def get_test_user_info(seed = None, first_name = None, last_name = None): |
| 13 | + if first_name is None: |
| 14 | + first_name = GMAIL_NAME |
115 | 15 |
|
| 16 | + if last_name is None: |
| 17 | + last_name = "" |
116 | 18 |
|
117 |
| - zip_error(page, assertion_errors) |
| 19 | + email = f"{GMAIL_NAME}+{seed}@gmail.com" if seed is not None else f"{GMAIL_NAME}@gmail.com" |
| 20 | + |
| 21 | + return {"email": email, "password": GMAIL_APP_PASSWORD, "first_name": first_name, "last_name": last_name} |
118 | 22 |
|
119 |
| - browser.close() |
| 23 | +def delete_email_inbox(user_email, password, retries=5, delay=10): |
| 24 | + imap = imaplib.IMAP4_SSL("imap.gmail.com") |
| 25 | + imap.login(user_email, password) |
120 | 26 |
|
121 | 27 |
|
122 |
| - if assertion_errors: |
123 |
| - print("\nAssertion Errors:") |
124 |
| - for error in assertion_errors: |
125 |
| - print(f"- {error}") |
126 |
| - raise AssertionError("One or more assertions failed. Check the logs above.") |
| 28 | + # Select inbox and delete all emails |
| 29 | + imap.select("inbox") |
| 30 | + status, all_emails = imap.search(None, "ALL") |
| 31 | + if status == "OK": |
| 32 | + for email_id in all_emails[0].split(): |
| 33 | + imap.store(email_id, "+FLAGS", "\\Deleted") |
| 34 | + imap.expunge() |
127 | 35 |
|
128 | 36 |
|
| 37 | +def get_magic_code(user_email, password, retries=5, delay=5): |
| 38 | + # Connect to the server |
| 39 | + imap = imaplib.IMAP4_SSL("imap.gmail.com") |
| 40 | + imap.login(user_email, password) |
| 41 | + |
| 42 | + for _ in range(retries): |
| 43 | + imap.select("inbox") |
| 44 | + status, messages = imap.search(None, '(UNSEEN SUBJECT "Expensify magic sign-in code:")') |
| 45 | + |
| 46 | + if status == "OK": |
| 47 | + email_ids = messages[0].split() |
| 48 | + print(email_ids) |
| 49 | + |
| 50 | + if email_ids: |
| 51 | + latest_email_id = email_ids[-1] |
| 52 | + status, msg_data = imap.fetch(latest_email_id, "(RFC822)") |
| 53 | + |
| 54 | + for response_part in msg_data: |
| 55 | + if isinstance(response_part, tuple): |
| 56 | + msg = email.message_from_bytes(response_part[1]) |
| 57 | + subject, encoding = decode_header(msg["Subject"])[0] |
| 58 | + if isinstance(subject, bytes): |
| 59 | + subject = subject.decode(encoding or "utf-8") |
| 60 | + |
| 61 | + # Search for the magic code in the subject |
| 62 | + match = re.search(r"Expensify magic sign-in code: (\d+)", subject) |
| 63 | + if match: |
| 64 | + code = match.group(1) |
| 65 | + imap.logout() |
| 66 | + return code |
| 67 | + else: |
| 68 | + print("No unread emails found with the subject. Retrying...") |
| 69 | + else: |
| 70 | + print("Failed to retrieve emails. Retrying...") |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + imap.logout() |
| 75 | + print("Max retries reached. Email not found.") |
| 76 | + return None |
| 77 | + |
| 78 | + |
| 79 | +def select_activity(page, first_name, last_name, activity_text): |
| 80 | + expect(page.get_by_text("What do you want to do today?")).to_be_visible() |
| 81 | + |
| 82 | + # Select activity in onboarding page and click Continue |
| 83 | + page.get_by_label(activity_text).click() |
| 84 | + |
| 85 | + # Enter first name, last name and click continue |
| 86 | + page.get_by_role("textbox", name="First name").fill(first_name) |
| 87 | + page.get_by_role("textbox", name="Last name").fill(last_name) |
| 88 | + page.get_by_role("button", name="Continue").last.click() |
| 89 | + |
| 90 | + |
| 91 | +def login_user(page, user_info, activity_text="Track and budget expenses"): |
| 92 | + # Clear cookies, local storage, and session storage |
| 93 | + page.context.clear_cookies() |
| 94 | + |
| 95 | + page.goto('https://dev.new.expensify.com:8082/') |
| 96 | + page.wait_for_load_state('load') |
| 97 | + |
| 98 | + page.get_by_test_id("username").fill(user_info["email"]) |
| 99 | + page.get_by_role("button", name="Continue").click() |
| 100 | + |
| 101 | + join_button = page.get_by_role("button", name="Join") |
| 102 | + validate_code_input = page.locator('input[data-testid="validateCode"]') |
| 103 | + expect(join_button.or_(validate_code_input)).to_be_visible() |
| 104 | + |
| 105 | + page.wait_for_timeout(5000) |
| 106 | + if (join_button.is_visible()): |
| 107 | + join_button.click(timeout=3000) |
| 108 | + else: |
| 109 | + # magic_code = get_magic_code(user_info["email"], user_info["password"], retries=6, delay=5) |
| 110 | + |
| 111 | + # if magic_code is None: |
| 112 | + # #Retrying again |
| 113 | + # page.locator(f"span:has-text('Didn't receive a magic code?')").first.click() |
| 114 | + # magic_code = get_magic_code(user_info["email"], user_info["password"], retries=6, delay=5) |
| 115 | + magic_code = "123456" |
| 116 | + print(f"Magic code: {magic_code}") |
| 117 | + validate_code_input.fill(magic_code) |
| 118 | + |
| 119 | + page.wait_for_timeout(3000) |
| 120 | + |
| 121 | + select_activity_dialog = page.get_by_text("What do you want to do today?") |
| 122 | + if select_activity_dialog.count() > 0: |
| 123 | + select_activity(page, user_info["first_name"], user_info["last_name"], activity_text) |
| 124 | + |
| 125 | + |
| 126 | +def launch_app(pw, headless=False, device=None, geolocation=None): |
| 127 | + browser = pw.chromium.launch(headless = headless, |
| 128 | + proxy = {"server": "http://127.0.0.1:8080/"}, slow_mo = 1000, |
| 129 | + args=[ |
| 130 | + "--ignore-certificate-errors", |
| 131 | + "--disable-web-security", |
| 132 | + "--disable-features=IsolateOrigins,site-per-process" |
| 133 | + ] |
| 134 | + ) |
| 135 | + |
| 136 | + context_args = {"viewport": {"width": 1024, "height": 640}} |
| 137 | + if device: |
| 138 | + context_args.update(pw.devices[device]) |
| 139 | + if geolocation: |
| 140 | + context_args["geolocation"] = geolocation |
| 141 | + context_args["permissions"] = ["geolocation"] |
| 142 | + context = browser.new_context(**context_args) |
| 143 | + page = context.new_page() |
| 144 | + return browser, context, page |
| 145 | + |
| 146 | + |
| 147 | +def test_55827(): |
| 148 | + with sync_playwright() as p: |
| 149 | + |
| 150 | + user_info = get_test_user_info() |
129 | 151 |
|
130 |
| -if __name__ == "__main__": |
131 |
| - try: |
132 |
| - test_expensify_0000() |
133 |
| - except AssertionError as e: |
134 |
| - print(str(e)) |
| 152 | + delete_email_inbox(user_info["email"], user_info["password"], retries=6, delay=5) |
| 153 | + |
| 154 | + browser, context, page = launch_app(p) |
| 155 | + login_user(page, user_info) |
| 156 | + |
| 157 | + page.wait_for_timeout(3000) |
| 158 | + |
| 159 | + page.get_by_test_id("3813452933783910").click() |
| 160 | + page.wait_for_timeout(3000) |
| 161 | + page.get_by_label("View details").click() |
| 162 | + page.wait_for_timeout(3000) |
| 163 | + page.locator("div:has-text('$20.00')").last.click() |
| 164 | + page.wait_for_timeout(3000) |
| 165 | + page.get_by_label("$20.00 for asd").last.click() |
| 166 | + page.wait_for_timeout(3000) |
| 167 | + page.get_by_label("Back").click() |
| 168 | + page.wait_for_timeout(3000) |
| 169 | + page.get_by_label("From Expense Report #").click() |
| 170 | + page.wait_for_timeout(3000) |
| 171 | + page.locator("div:has-text('$20.00')").last.click(button="right") |
| 172 | + page.wait_for_timeout(3000) |
| 173 | + |
| 174 | + text_locator = page.get_by_text("Hold") |
| 175 | + expect(text_locator).to_be_visible() |
| 176 | + |
| 177 | + page.close() |
| 178 | + browser.close() |
0 commit comments