diff --git a/tests/test_e2e_playwright.py b/tests/test_e2e_playwright.py index ce694ac..1dd9722 100644 --- a/tests/test_e2e_playwright.py +++ b/tests/test_e2e_playwright.py @@ -283,3 +283,81 @@ def test_homepage_and_options_page_render() -> None: assert "converted collateral spot" in hedge_spot_text or "configured entry price" in hedge_spot_text browser.close() + + +def test_backtest_page_loads_with_valid_databento_dates() -> None: + """E2E test: Backtest page loads and validates Databento date range. + + Regression test for CORE-003: Ensures backtest page handles Databento + dataset date constraints gracefully without 500 errors. + """ + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={"width": 1440, "height": 1000}) + + # Navigate to backtests page + page.goto(f"{BASE_URL}/backtests", wait_until="domcontentloaded", timeout=30000) + page.wait_for_load_state("networkidle", timeout=15000) + + # Verify page loaded without 500 error + expect(page.locator("text=Scenario Configuration")).to_be_visible(timeout=10000) + + # Verify data source is set to Databento by default + data_source = page.locator("[data-testid=data-source-select]") + expect(data_source).to_be_visible() + + # Verify dataset is XNAS.BASIC + dataset = page.locator("[data-testid=dataset-select]") + expect(dataset).to_be_visible() + + # Verify date range hint shows correct minimum date for XNAS.BASIC + date_hint = page.locator("text=XNAS.BASIC data available from 2024-07-01") + expect(date_hint).to_be_visible(timeout=5000) + + # Verify start date input is set to valid date (2024-07-01 or later) + start_input = page.locator("input[placeholder*='Start date']").first + start_value = start_input.input_value() + assert start_value >= "2024-07-01", f"Start date {start_value} should be >= 2024-07-01" + + # Verify no 500 error on page + error_500 = page.locator("text=500").count() + assert error_500 == 0, "Page should not show 500 error" + + page.screenshot(path=str(ARTIFACTS / "backtest_loads.png"), full_page=True) + browser.close() + + +def test_backtest_page_handles_invalid_dates_gracefully() -> None: + """E2E test: Backtest page shows validation error for invalid dates. + + Regression test: Ensures user-friendly error instead of 500 when + dates are before dataset availability. + """ + with sync_playwright() as p: + browser = p.chromium.launch(headless=True) + page = browser.new_page(viewport={"width": 1440, "height": 1000}) + + page.goto(f"{BASE_URL}/backtests", wait_until="domcontentloaded", timeout=30000) + page.wait_for_load_state("networkidle", timeout=15000) + + # Set invalid start date (before 2024-07-01) + start_input = page.locator("input[placeholder*='Start date']").first + start_input.fill("2024-03-01") + start_input.press("Tab") # Trigger blur/validation + + page.wait_for_timeout(2000) + + # Should show validation error or prevent running, not crash + # Check for validation message + has_validation = ( + page.locator("text=Invalid start date").is_visible() or + page.locator("text=data available from").is_visible() or + page.locator("text=warning").is_visible() + ) + + # Verify no 500 error + error_500 = page.locator("text=500").count() + assert error_500 == 0, "Page should not show 500 error for invalid dates" + + page.screenshot(path=str(ARTIFACTS / "backtest_invalid_dates.png"), full_page=True) + browser.close()