-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
59187b3
commit f1e2e61
Showing
841 changed files
with
31,420 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
7f6169a4eac2021119365a4f9d5124a896439d27 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"price": 250.0, | ||
"title": "[HOLD for payment 2024-11-20] [$250] Workspace list is opened when opening a WS share code without any access to it", | ||
"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 contributors@expensify.com to request to join our Slack channel!\r\n___\r\n\r\n**Version Number:** 9.0.50-0\r\n**Reproducible in staging?:** Y\r\n**Reproducible in production?:** Y\r\n**If this was caught on HybridApp, is this reproducible on New Expensify Standalone?:** \r\n**Found when validation PR** https://github.com/Expensify/App/pull/50875\r\n**Logs:** https://stackoverflow.com/c/expensify/questions/4856\r\n**Issue reported by:** Applause-Internal team\r\n\r\n\r\n## Action Performed:\r\nPreconditions: Uninstall ND app. A Gmail user should be at it's own workspace share code page on web.\r\n\r\n1. Navigate to https://staging.new.expensify.com/\r\n2. Log in with a different, new Gmail user\r\n3. Open iOS \"Camera\" app\r\n4. Point the feed to the QR code\r\n5. Tap on the button to navigate to it\r\n\r\n## Expected Result:\r\nI should be navigated to the \"it's not here\" page with an option to request access.\r\n\r\n## Actual Result:\r\nWorkspace list is opened when opening a WS share code without any access to it.\r\n\r\n## Workaround:\r\nUnknown\r\n\r\n## Platforms:\r\n<!---\r\nCheck off any platforms that are affected by this issue\r\n--->\r\nWhich of our officially supported platforms is this issue occurring on?\r\n- [ ] Android: Standalone\r\n- [x] Android: HybridApp\r\n- [ ] Android: mWeb Chrome\r\n- [ ] iOS: Standalone\r\n- [ ] iOS: HybridApp\r\n- [x] iOS: mWeb Safari\r\n- [x] MacOS: Chrome / Safari\r\n- [ ] MacOS: Desktop\r\n\r\n## Screenshots/Videos\r\n\r\n\r\nhttps://github.com/user-attachments/assets/b74078d2-2c9a-4791-ac8f-79a931caf945\r\n\r\n\r\n\r\n \r\n</details>\r\n\r\n[View all open jobs on GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22)\r\n\n<details><summary>Upwork Automation - Do Not Edit</summary>\n <ul>\n <li>Upwork Job URL: https://www.upwork.com/jobs/~021847411075396403416</li>\n <li>Upwork Job ID: 1847411075396403416</li>\n <li>Last Price Increase: 2024-10-18</li>\n </ul>\n</details>\n\n\n\n", | ||
"_issue_id": "51000" | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
git reset --hard d203c4da550d2582933f856bf016ad8350955019 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import os | ||
import random | ||
import string | ||
|
||
import pytest | ||
from playwright.async_api import Browser, Page, TimeoutError, async_playwright | ||
|
||
WORKSPACE_NAME = "pyPtFh23" | ||
EMAIL_USERNAME = "xecuycismfsga" | ||
EMAIL_ALIAS = "kj56jrdw" | ||
USER_EMAIL = f"{EMAIL_USERNAME}+{EMAIL_ALIAS}@gmail.com" | ||
PASSWORD = "uwgb zzoc cofa kaaq" | ||
SLOW_MO: int | None = 500 | ||
PROXY_URL = os.getenv("PROXY_URL") | ||
|
||
|
||
def generate_random_string(length=6): | ||
letters_and_digits = string.ascii_letters + string.digits | ||
return "".join(random.choice(letters_and_digits) for _ in range(length)) | ||
|
||
|
||
def generate_random_email(alias: str = generate_random_string()): | ||
return f"{EMAIL_USERNAME}+{alias}@gmail.com" | ||
|
||
|
||
async def get_magic_code( | ||
_page: Page, _user_email: str = USER_EMAIL, _password: str = PASSWORD | ||
): | ||
return "123456" | ||
|
||
|
||
async def create_user(page: Page, firstname: str = "User", lastname: str = EMAIL_ALIAS): | ||
await page.get_by_role("button", name="Join").click() | ||
|
||
# Update profile | ||
await page.get_by_text("Track and budget expenses").click() | ||
await page.get_by_role("textbox", name="First name").fill(firstname) | ||
await page.get_by_role("textbox", name="Last name").fill(lastname) | ||
await page.get_by_role("button", name="Continue").click() | ||
|
||
|
||
async def login(page: Page): | ||
# get current timestamp | ||
magic_code = await get_magic_code(page) | ||
|
||
if magic_code is None: | ||
raise ValueError("Failed to retrieve magic code") | ||
|
||
await page.get_by_role("textbox").fill(magic_code) | ||
|
||
|
||
async def login_or_create_user( | ||
page: Page, | ||
last_name: str = EMAIL_ALIAS, | ||
user_email: str = USER_EMAIL, | ||
): | ||
await page.goto("https://dev.new.expensify.com:8082/") | ||
await page.get_by_test_id("username").fill(user_email) | ||
await page.get_by_role("button", name="Continue").click() | ||
|
||
try: | ||
await page.get_by_role("button", name="Join").wait_for( | ||
state="visible", timeout=2000 | ||
) | ||
await create_user(page, last_name) | ||
except TimeoutError: | ||
await login(page) | ||
|
||
await page.get_by_label("Inbox").wait_for(state="visible", timeout=10000) | ||
|
||
|
||
async def create_workspace(page: Page, workspace_name: str = WORKSPACE_NAME): | ||
""" | ||
Create a workspace if it does not already exist | ||
""" | ||
await page.get_by_label("My Settings").click() | ||
await page.get_by_test_id("InitialSettingsPage").get_by_label("Workspaces").click() | ||
|
||
try: | ||
await ( | ||
page.locator('button[aria-label="row"]') | ||
.filter(has_text=workspace_name) | ||
.last.click(timeout=3000) | ||
) | ||
except TimeoutError: | ||
await page.get_by_label("New workspace").last.click() | ||
|
||
await page.get_by_text("Name", exact=True).click() | ||
name_input = page.get_by_role("textbox", name="Name") | ||
await name_input.clear() | ||
await name_input.type(workspace_name, delay=200) | ||
await page.get_by_role("button", name="Save").click() | ||
|
||
|
||
async def setup_workspace(browser: Browser): | ||
admin_context = await browser.new_context( | ||
permissions=["clipboard-read", "clipboard-write"] | ||
) | ||
admin_page = await admin_context.new_page() | ||
|
||
await login_or_create_user(admin_page) | ||
|
||
await create_workspace(admin_page) | ||
|
||
await admin_page.get_by_role("button", name="Share").click() | ||
await admin_page.get_by_label("Copy URL").click() | ||
await admin_page.wait_for_timeout(1000) # wait for clipboard to be populated | ||
workspace_url = await admin_page.evaluate("navigator.clipboard.readText()") | ||
return workspace_url | ||
|
||
|
||
@pytest.mark.asyncio(scope="session") | ||
async def test_workspace_access(): | ||
async with async_playwright() as p: | ||
browser = await p.chromium.launch( | ||
proxy={"server": PROXY_URL} if PROXY_URL else None, | ||
headless=False, | ||
args=[ | ||
"--no-sandbox", | ||
"--disable-dev-shm-usage", | ||
"--ignore-certificate-errors", | ||
"--disable-web-security", | ||
"--disable-features=IsolateOrigins,site-per-process", | ||
], | ||
slow_mo=SLOW_MO, | ||
channel="chromium", | ||
) | ||
|
||
workspace_url = await setup_workspace(browser) | ||
|
||
context = await browser.new_context() | ||
page = await context.new_page() | ||
|
||
restricted_user_alias = generate_random_string() | ||
restricted_user_email = generate_random_email(restricted_user_alias) | ||
|
||
await login_or_create_user( | ||
page, user_email=restricted_user_email, last_name=restricted_user_alias | ||
) | ||
|
||
await page.goto(workspace_url) | ||
|
||
await ( | ||
page.locator('button[aria-label="row"]') | ||
.filter(has_text=WORKSPACE_NAME) | ||
.last.wait_for(state="visible", timeout=10000) | ||
) | ||
|
||
# Close all tabs and browser | ||
await page.close() | ||
await context.close() | ||
await browser.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import os | ||
import random | ||
import string | ||
|
||
import pytest | ||
from playwright.async_api import Browser, Page, TimeoutError, async_playwright | ||
from utils.trace_cleaner import trace_cleaner | ||
|
||
WORKSPACE_NAME = "pyPtFh23" | ||
EMAIL_USERNAME = "xecuycismfsga" | ||
EMAIL_ALIAS = "kj56jrdw" | ||
USER_EMAIL = f"{EMAIL_USERNAME}+{EMAIL_ALIAS}@gmail.com" | ||
PASSWORD = "uwgb zzoc cofa kaaq" | ||
SLOW_MO: int | None = 500 | ||
PROXY_URL = os.getenv("PROXY_URL") | ||
|
||
|
||
def generate_random_string(length=6): | ||
letters_and_digits = string.ascii_letters + string.digits | ||
return "".join(random.choice(letters_and_digits) for _ in range(length)) | ||
|
||
|
||
def generate_random_email(alias: str = generate_random_string()): | ||
return f"{EMAIL_USERNAME}+{alias}@gmail.com" | ||
|
||
|
||
async def get_magic_code( | ||
_page: Page, _user_email: str = USER_EMAIL, _password: str = PASSWORD | ||
): | ||
return "123456" | ||
|
||
|
||
async def create_user(page: Page, firstname: str = "User", lastname: str = EMAIL_ALIAS): | ||
await page.get_by_role("button", name="Join").click() | ||
|
||
# Update profile | ||
await page.get_by_text("Track and budget expenses").click() | ||
await page.get_by_role("textbox", name="First name").fill(firstname) | ||
await page.get_by_role("textbox", name="Last name").fill(lastname) | ||
await page.get_by_role("button", name="Continue").click() | ||
|
||
|
||
async def login(page: Page): | ||
# get current timestamp | ||
magic_code = await get_magic_code(page) | ||
|
||
if magic_code is None: | ||
raise ValueError("Failed to retrieve magic code") | ||
|
||
await page.get_by_role("textbox").fill(magic_code) | ||
|
||
|
||
async def login_or_create_user( | ||
page: Page, | ||
last_name: str = EMAIL_ALIAS, | ||
user_email: str = USER_EMAIL, | ||
): | ||
await page.goto("https://dev.new.expensify.com:8082/") | ||
await page.get_by_test_id("username").fill(user_email) | ||
await page.get_by_role("button", name="Continue").click() | ||
|
||
try: | ||
await page.get_by_role("button", name="Join").wait_for( | ||
state="visible", timeout=2000 | ||
) | ||
await create_user(page, last_name) | ||
except TimeoutError: | ||
await login(page) | ||
|
||
await page.get_by_label("Inbox").wait_for(state="visible", timeout=10000) | ||
|
||
|
||
async def create_workspace(page: Page, workspace_name: str = WORKSPACE_NAME): | ||
""" | ||
Create a workspace if it does not already exist | ||
""" | ||
await page.get_by_label("My Settings").click() | ||
await page.get_by_test_id("InitialSettingsPage").get_by_label("Workspaces").click() | ||
|
||
try: | ||
await ( | ||
page.locator('button[aria-label="row"]') | ||
.filter(has_text=workspace_name) | ||
.last.click(timeout=3000) | ||
) | ||
except TimeoutError: | ||
await page.get_by_label("New workspace").last.click() | ||
|
||
await page.get_by_text("Name", exact=True).click() | ||
name_input = page.get_by_role("textbox", name="Name") | ||
await name_input.clear() | ||
await name_input.type(workspace_name, delay=200) | ||
await page.get_by_role("button", name="Save").click() | ||
|
||
|
||
async def setup_workspace(browser: Browser): | ||
admin_context = await browser.new_context( | ||
permissions=["clipboard-read", "clipboard-write"] | ||
) | ||
# Start tracing for admin context | ||
await admin_context.tracing.start(screenshots=True, snapshots=True, sources=True) | ||
admin_page = await admin_context.new_page() | ||
|
||
await login_or_create_user(admin_page) | ||
|
||
await create_workspace(admin_page) | ||
|
||
await admin_page.get_by_role("button", name="Share").click() | ||
await admin_page.get_by_label("Copy URL").click() | ||
await admin_page.wait_for_timeout(1000) # wait for clipboard to be populated | ||
workspace_url = await admin_page.evaluate("navigator.clipboard.readText()") | ||
return workspace_url, admin_context | ||
|
||
|
||
@pytest.mark.asyncio(scope="session") | ||
async def test_workspace_access(): | ||
async with async_playwright() as p: | ||
browser = await p.chromium.launch( | ||
proxy={"server": PROXY_URL} if PROXY_URL else None, | ||
headless=False, | ||
args=[ | ||
"--no-sandbox", | ||
"--disable-dev-shm-usage", | ||
"--ignore-certificate-errors", | ||
"--disable-web-security", | ||
"--disable-features=IsolateOrigins,site-per-process", | ||
], | ||
slow_mo=SLOW_MO, | ||
channel="chromium", | ||
) | ||
# Setup workspace using admin context and start its tracing above | ||
workspace_url, admin_context = await setup_workspace(browser) | ||
|
||
# Create a new context for the restricted user | ||
context = await browser.new_context() | ||
# Start tracing for the restricted user context | ||
await context.tracing.start(screenshots=True, snapshots=True, sources=True) | ||
page = await context.new_page() | ||
|
||
# Wrap the main test logic in try/finally to ensure tracing stops and trace exported | ||
try: | ||
restricted_user_alias = generate_random_string() | ||
restricted_user_email = generate_random_email(restricted_user_alias) | ||
|
||
await login_or_create_user( | ||
page, user_email=restricted_user_email, last_name=restricted_user_alias | ||
) | ||
|
||
await page.goto(workspace_url) | ||
|
||
await ( | ||
page.locator('button[aria-label="row"]') | ||
.filter(has_text=WORKSPACE_NAME) | ||
.last.wait_for(state="visible", timeout=10000) | ||
) | ||
finally: | ||
# Stop tracing and export trace for restricted user context | ||
restricted_trace_path = "/app/expensify/user_tool/output_browser2.zip" | ||
await context.tracing.stop(path=restricted_trace_path) | ||
trace_cleaner(restricted_trace_path) | ||
await page.close() | ||
await context.close() | ||
|
||
# Stop tracing and export trace for admin context | ||
admin_trace_path = "/app/expensify/user_tool/output_browser1.zip" | ||
# Retrieve the admin page from admin_context if needed before stopping tracing | ||
await admin_context.tracing.stop(path=admin_trace_path) | ||
trace_cleaner(admin_trace_path) | ||
await admin_context.close() | ||
|
||
# Close the browser after all tracing exports | ||
await browser.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
6e2e36e042d41f652f1e878443c32916670708d4 |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"price": 50.0, | ||
"title": "[HOLD for payment 2024-12-03] [$50] Update copy on the app preferences page", | ||
"issue_repo_steps": "# Problem\r\nWhen users find it difficult to navigate our application's features due to interface clutter, it leads to decreased engagement and lower conversion and retention rates.\r\n\r\n# Solution\r\nClean up some of the copy on the app preferences page:\r\n\r\n1. Remove the text \"Customize your Expensify account.\"\r\n2. Remove the section header for \"Notifications\"\r\n\r\n\r\n\r\n\n<details><summary>Upwork Automation - Do Not Edit</summary>\n <ul>\n <li>Upwork Job URL: https://www.upwork.com/jobs/~021859527407524347826</li>\n <li>Upwork Job ID: 1859527407524347826</li>\n <li>Last Price Increase: 2024-11-21</li>\n<li>Automatic offers: </li>\n<ul>\n<li>brunovjk | Reviewer | 105008786</li>\n</ul></li>\n </ul>\n</details>\n\n<details><summary>Issue Owner</summary>Current Issue Owner: @JmillsExpensify</details>", | ||
"_issue_id": "52790" | ||
} |
Empty file.
Oops, something went wrong.