issues/192/user_tool.py (121 lines of code) (raw):

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 = "" 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()