diff --git a/README.md b/README.md index 14ddee3..9aeccb0 100644 --- a/README.md +++ b/README.md @@ -55,4 +55,8 @@ The container entrypoint wraps commands in `xvfb-run`, which provides the virtua ## Exploration -`exploration/explore.py` is a helper for writing new tests: it navigates to a path (optionally logging in first) and dumps a screenshot plus the rendered page source so selectors can be inspected without running a full test. +`exploration/explore.py` is a helper for writing new tests: it navigates to a path (optionally logging in first) and dumps a screenshot plus the rendered page source so selectors can be inspected without running a full test. Pass `--click ` (repeatable; CSS, or XPath if it starts with `//`) to click elements — e.g. open a menu or flip a toggle — before the capture: + +```bash +uv run python exploration/explore.py --login user --click "#integration-menu-button" +``` diff --git a/exploration/explore.py b/exploration/explore.py index d9a7aeb..e7a3853 100644 --- a/exploration/explore.py +++ b/exploration/explore.py @@ -1,12 +1,14 @@ """ Exploration helper for writing Selenium tests. -Usage: python explore.py [--login builder|user|admin] +Usage: python explore.py [--login builder|user] [--click ...] -Navigates to TEST_DOMAIN+url_path, optionally logs in first, -then saves a screenshot and page source for inspection. +Navigates to TEST_DOMAIN+url_path, optionally logs in first, optionally +clicks elements (e.g. to open a menu or flip a toggle), then saves a +screenshot and page source for inspection. """ import os +import time import argparse from selenium.webdriver import Chrome @@ -53,8 +55,14 @@ def wait_for_page(browser): ) +def click(browser, selector): + by = By.XPATH if selector.startswith(("//", "(")) else By.CSS_SELECTOR + element = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((by, selector))) + element.click() + time.sleep(1) # let menus/animations settle before the capture + + def save_outputs(browser): - wait_for_page(browser) browser.save_screenshot(OUTPUT_SCREENSHOT) with open(OUTPUT_HTML, "w", encoding="utf-8") as f: f.write(browser.page_source) @@ -68,6 +76,14 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument("path", nargs="?", default="", help="URL path to append to TEST_DOMAIN") parser.add_argument("--login", choices=CREDENTIALS.keys(), help="Log in as this role first") + parser.add_argument( + "--click", + action="append", + default=[], + metavar="SELECTOR", + help="Click this element after the page loads, before capturing " + "(CSS selector, or XPath if it starts with //; repeatable, clicked in order)", + ) args = parser.parse_args() domain = os.environ["TEST_DOMAIN"].rstrip("/") @@ -78,6 +94,9 @@ def main(): if args.login: login(browser, args.login) browser.get(target) + wait_for_page(browser) + for selector in args.click: + click(browser, selector) save_outputs(browser) finally: browser.quit()