From 43feecaf54f1510fb99b3f819631a6080aa836a4 Mon Sep 17 00:00:00 2001 From: rcholic Date: Sun, 21 Dec 2025 19:07:02 -0800 Subject: [PATCH] fix tests --- sentience/browser.py | 11 ++++++++--- tests/conftest.py | 8 ++++++++ tests/test_actions.py | 6 +++--- tests/test_generator.py | 12 ++++++------ tests/test_inspector.py | 8 ++++---- tests/test_query.py | 4 ++-- tests/test_recorder.py | 18 +++++++++--------- tests/test_smart_selector.py | 6 +++--- tests/test_snapshot.py | 6 +++--- tests/test_spec_validation.py | 2 +- tests/test_stealth.py | 2 +- tests/test_wait.py | 10 ++++++---- 12 files changed, 54 insertions(+), 39 deletions(-) diff --git a/sentience/browser.py b/sentience/browser.py index 521a964..2f74788 100644 --- a/sentience/browser.py +++ b/sentience/browser.py @@ -24,7 +24,7 @@ def __init__( self, api_key: Optional[str] = None, api_url: Optional[str] = None, - headless: bool = False + headless: Optional[bool] = None ): """ Initialize Sentience browser @@ -36,7 +36,7 @@ def __init__( If None and api_key is provided, uses default URL If None and no api_key, uses free tier (local extension only) If 'local' or Docker sidecar URL, uses Enterprise tier - headless: Whether to run in headless mode + headless: Whether to run in headless mode. If None, defaults to True in CI, False otherwise """ self.api_key = api_key # Only set api_url if api_key is provided, otherwise None (free tier) @@ -45,7 +45,12 @@ def __init__( self.api_url = api_url or "https://api.sentienceapi.com" else: self.api_url = None - self.headless = headless + # Default to headless=True in CI (no X server), headless=False locally + if headless is None: + import os + self.headless = os.getenv("CI", "").lower() in ("true", "1", "yes") + else: + self.headless = headless self.playwright: Optional[Playwright] = None self.context: Optional[BrowserContext] = None self.page: Optional[Page] = None diff --git a/tests/conftest.py b/tests/conftest.py index a1d7ccf..5d6b57b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,6 +13,14 @@ def pytest_configure(config): ) +@pytest.fixture +def headless(): + """Fixture that returns headless mode based on CI environment""" + # In CI, always use headless mode (no X server available) + # Locally, default to False (headed) for better debugging + return os.getenv("CI", "").lower() in ("true", "1", "yes") + + @pytest.fixture(scope="session") def extension_available(): """Check if the sentience-chrome extension is available""" diff --git a/tests/test_actions.py b/tests/test_actions.py index 986f96d..b7bd0e2 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -8,7 +8,7 @@ def test_click(): """Test click action""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -24,7 +24,7 @@ def test_click(): def test_type_text(): """Test type action""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: # Use a page with a text input browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -41,7 +41,7 @@ def test_type_text(): def test_press(): """Test press action""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_generator.py b/tests/test_generator.py index ca85f3c..7d9d98d 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -12,7 +12,7 @@ def test_generator_python(): """Test Python script generation""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -37,7 +37,7 @@ def test_generator_python(): def test_generator_typescript(): """Test TypeScript script generation""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -57,7 +57,7 @@ def test_generator_typescript(): def test_generator_save_python(): """Test saving generated Python script""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -82,7 +82,7 @@ def test_generator_save_python(): def test_generator_save_typescript(): """Test saving generated TypeScript script""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -107,7 +107,7 @@ def test_generator_save_typescript(): def test_generator_without_selector(): """Test generator handles steps without selectors""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -124,7 +124,7 @@ def test_generator_without_selector(): def test_generate_helper(): """Test generate() helper function""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_inspector.py b/tests/test_inspector.py index f3b07d1..6bbaece 100644 --- a/tests/test_inspector.py +++ b/tests/test_inspector.py @@ -8,7 +8,7 @@ def test_inspector_start_stop(): """Test inspector can start and stop""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -28,7 +28,7 @@ def test_inspector_start_stop(): def test_inspector_context_manager(): """Test inspector as context manager""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -44,7 +44,7 @@ def test_inspector_context_manager(): def test_inspector_mouse_move_detection(): """Test inspector detects mouse move""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -60,7 +60,7 @@ def test_inspector_mouse_move_detection(): def test_inspector_click_detection(): """Test inspector detects clicks""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_query.py b/tests/test_query.py index b7b9545..d581713 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -155,7 +155,7 @@ def test_match_element(): def test_query_integration(): """Test query on real page""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -174,7 +174,7 @@ def test_query_integration(): def test_find_integration(): """Test find on real page""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_recorder.py b/tests/test_recorder.py index eef0610..21a0875 100644 --- a/tests/test_recorder.py +++ b/tests/test_recorder.py @@ -11,7 +11,7 @@ def test_recorder_start_stop(): """Test recorder can start and stop""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -26,7 +26,7 @@ def test_recorder_start_stop(): def test_recorder_context_manager(): """Test recorder as context manager""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -39,7 +39,7 @@ def test_recorder_context_manager(): def test_recorder_navigation(): """Test recording navigation events""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -53,7 +53,7 @@ def test_recorder_navigation(): def test_recorder_click(): """Test recording click events""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -68,7 +68,7 @@ def test_recorder_click(): def test_recorder_type(): """Test recording type events""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -84,7 +84,7 @@ def test_recorder_type(): def test_recorder_type_masking(): """Test text masking in type events""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -98,7 +98,7 @@ def test_recorder_type_masking(): def test_recorder_press(): """Test recording key press events""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -112,7 +112,7 @@ def test_recorder_press(): def test_trace_save_load(): """Test trace save and load""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -142,7 +142,7 @@ def test_trace_save_load(): def test_trace_format(): """Test trace format matches spec""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_smart_selector.py b/tests/test_smart_selector.py index 4c56504..66da62d 100644 --- a/tests/test_smart_selector.py +++ b/tests/test_smart_selector.py @@ -8,7 +8,7 @@ def test_smart_selector_inference(): """Test that recorder infers selectors automatically""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -30,7 +30,7 @@ def test_smart_selector_inference(): def test_smart_selector_with_text(): """Test selector inference for elements with text""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -54,7 +54,7 @@ def test_smart_selector_with_text(): def test_smart_selector_validation(): """Test that inferred selectors are validated""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index febe3c5..0b58a0b 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -10,7 +10,7 @@ @pytest.mark.requires_extension def test_snapshot_basic(): """Test basic snapshot on example.com""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -33,7 +33,7 @@ def test_snapshot_roundtrip(): ] for site in sites: - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto(site) browser.page.wait_for_load_state("networkidle") @@ -66,7 +66,7 @@ def test_snapshot_save(): import os import json - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_spec_validation.py b/tests/test_spec_validation.py index f4cbb38..a414d3c 100644 --- a/tests/test_spec_validation.py +++ b/tests/test_spec_validation.py @@ -65,7 +65,7 @@ def test_snapshot_matches_spec(): """Test that snapshot response matches spec schema""" schema = load_schema() - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") diff --git a/tests/test_stealth.py b/tests/test_stealth.py index 2cb8184..18854dc 100644 --- a/tests/test_stealth.py +++ b/tests/test_stealth.py @@ -25,7 +25,7 @@ def test_stealth_features(): print("Bot Evasion / Stealth Mode Test") print("=" * 60) - browser = SentienceBrowser(headless=False) + browser = SentienceBrowser() try: browser.start() diff --git a/tests/test_wait.py b/tests/test_wait.py index 1428a20..fc50823 100644 --- a/tests/test_wait.py +++ b/tests/test_wait.py @@ -3,12 +3,14 @@ """ import pytest +import os from sentience import SentienceBrowser, wait_for, expect def test_wait_for(): """Test wait_for element""" - with SentienceBrowser(headless=False) as browser: + # Auto-detect headless mode (True in CI, False locally) + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -21,7 +23,7 @@ def test_wait_for(): def test_wait_for_timeout(): """Test wait_for timeout""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -33,7 +35,7 @@ def test_wait_for_timeout(): def test_expect_to_exist(): """Test expect().to_exist()""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle") @@ -44,7 +46,7 @@ def test_expect_to_exist(): def test_expect_to_be_visible(): """Test expect().to_be_visible()""" - with SentienceBrowser(headless=False) as browser: + with SentienceBrowser() as browser: browser.page.goto("https://example.com") browser.page.wait_for_load_state("networkidle")