Skip to content

Commit 644d279

Browse files
Code cleanup (#39)
* reorganize files * Delete add_git_tag.py
1 parent 53b864b commit 644d279

File tree

2,590 files changed

+87736
-73651
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,590 files changed

+87736
-73651
lines changed

issues/1/commit_id.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
da2e6688c3f16e8db76d2bcf4b098be5990e8968
1+
bde67d0e2a370e7470e59b038a8ff920ec4fab6c

issues/1/flow.mitm

83.1 KB
Binary file not shown.

issues/1/issue_data.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"price": 8000.0,
3-
"title": "[Paid] [$8000] zip /postcode validation error message not displayed for entering `,` on the Home address screen",
4-
"issue_repo_steps": "Action performed: 1. go to Settings > profile> personal details >Home address\r\n2. type the zip /postcode as ,\n\nExpected result: it should show validation error message\n\nActual result: None",
5-
"_issue_id": "14958"
2+
"price": 250.0,
3+
"title": "[HOLD for payment 2025-02-06] [$250] Expense - Hold option is missing in the context menu",
4+
"issue_repo_steps": "If you haven\u2019t already, check out our [contributing guidelines](https://github.com/Expensify/ReactNativeChat/blob/main/contributingGuides/CONTRIBUTING.md) for onboarding and email [email protected] to request to join our Slack channel!\n___\n\n**Version Number:** 9.0.90-0\n**Reproducible in staging?:** Yes\n**Reproducible in production?:** No\n**If this was caught on HybridApp, is this reproducible on New Expensify Standalone?:** N/A\n**If this was caught during regression testing, add the test name, ID and link from TestRail:** Exp\n**Email or phone of affected tester (no customers):** [email protected]\n**Issue reported by:** Applause Internal Team\n**Device used:** Mac 15.0 / Chrome\n**App Component:** Money Requests\n\n## Action Performed:\n1. Go to staging.new.expensify.com\n2. Go to workspace chat.\n3. Submit two expenses to the workspace chat.\n4. Go to expense report.\n5. Click on the expense preview.\n6. Go back to the expense report.\n7. Right click on the expense preview.\n\n## Expected Result:\nThere should be Hold option in the context menu (production behavior).\n\n## Actual Result:\nHold option is missing in the context menu.\n\n## Workaround:\nUnknown\n\n## Platforms:\n- [x] Android: Standalone\n- [x] Android: HybridApp\n- [x] Android: mWeb Chrome\n- [x] iOS: Standalone\n- [x] iOS: HybridApp\n- [x] iOS: mWeb Safari\n- [x] MacOS: Chrome / Safari\n- [x] MacOS: Desktop\n\n## Screenshots/Videos\n\nhttps://github.com/user-attachments/assets/b821e159-ea71-4d2d-836c-ebd605fb42c0\n\n[View all open jobs on GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)\n<details><summary>Upwork Automation - Do Not Edit</summary>\n <ul>\n <li>Upwork Job URL: https://www.upwork.com/jobs/~021884172494858147022</li>\n <li>Upwork Job ID: 1884172494858147022</li>\n <li>Last Price Increase: 2025-01-28</li>\n </ul>\n</details>\n\n<details><summary>Issue Owner</summary>Current Issue Owner: @</details>\n\n<details><summary>Issue Owner</summary>Current Issue Owner: @mallenexpensify</details>",
5+
"_issue_id": "55827"
66
}

issues/1/issue_introduction.patch

-22
Original file line numberDiff line numberDiff line change
@@ -1,22 +0,0 @@
1-
diff --git a/src/CONST.ts b/src/CONST.ts
2-
index 8e38812ccdc..2628d574257 100755
3-
--- a/src/CONST.ts
4-
+++ b/src/CONST.ts
5-
@@ -3615,7 +3615,7 @@ const CONST = {
6-
},
7-
GA: {},
8-
GB: {
9-
- regex: /^[A-Z]{1,2}[0-9R][0-9A-Z]?\s*[0-9][A-Z-CIKMOV]{2}$/,
10-
+ regex: /^(,|[A-Z]{1,2}[0-9R][0-9A-Z]?\s*([0-9][ABD-HJLNP-UW-Z]{2})?)$/,
11-
samples: 'LA102UX, BL2F8FX, BD1S9LU, WR4G 6LH',
12-
},
13-
GD: {},
14-
@@ -4134,7 +4134,7 @@ const CONST = {
15-
UG: {},
16-
UM: {},
17-
US: {
18-
- regex: /^[0-9]{5}(?:[- ][0-9]{4})?$/,
19-
+ regex: /^(,|[A-Za-z0-9]{5,10})$/,
20-
samples: '12345, 12345-1234, 12345 1234',
21-
},
22-
UY: {

issues/1/revert_command.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
git reset --hard 75bf54eb0166d846af9836bd6e95787b143bc15e

issues/1/test.py

+165-121
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,178 @@
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
81
import imaplib
92
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
1066

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"
11210

11311

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
11515

16+
if last_name is None:
17+
last_name = ""
11618

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}
11822

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)
12026

12127

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()
12735

12836

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()
129151

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

Comments
 (0)