From 73e76ebca676f4674466b7789cebdac7366a8663 Mon Sep 17 00:00:00 2001 From: Thalison Fernandes Date: Sun, 24 Aug 2025 17:48:11 -0300 Subject: [PATCH 1/2] feat: add configurable page load state --- pydoll/browser/interfaces.py | 12 ++++++++++++ pydoll/browser/options.py | 10 ++++++++++ pydoll/browser/tab.py | 5 ++++- pydoll/constants.py | 5 +++++ tests/test_browser/test_browser_options.py | 20 ++++++++++++++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/pydoll/browser/interfaces.py b/pydoll/browser/interfaces.py index 48fff1da..d40ed765 100644 --- a/pydoll/browser/interfaces.py +++ b/pydoll/browser/interfaces.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod +from pydoll.constants import PageLoadState + class Options(ABC): @property @@ -36,6 +38,16 @@ def headless(self) -> bool: def headless(self, headless: bool): pass + @property + @abstractmethod + def page_load_state(self) -> PageLoadState: + pass + + @page_load_state.setter + @abstractmethod + def page_load_state(self, state: PageLoadState): + pass + class BrowserOptionsManager(ABC): @abstractmethod diff --git a/pydoll/browser/options.py b/pydoll/browser/options.py index bd545bfe..9c7e5bef 100644 --- a/pydoll/browser/options.py +++ b/pydoll/browser/options.py @@ -1,6 +1,7 @@ from contextlib import suppress from pydoll.browser.interfaces import Options +from pydoll.constants import PageLoadState from pydoll.exceptions import ( ArgumentAlreadyExistsInOptions, ArgumentNotFoundInOptions, @@ -28,6 +29,7 @@ def __init__(self): self._start_timeout = 10 self._browser_preferences = {} self._headless = False + self._page_load_state = PageLoadState.COMPLETE @property def arguments(self) -> list[str]: @@ -316,3 +318,11 @@ def headless(self, headless: bool): if headless == has_argument: return methods_map[headless]('--headless') + + @property + def page_load_state(self) -> PageLoadState: + return self._page_load_state + + @page_load_state.setter + def page_load_state(self, state: PageLoadState): + self._page_load_state = state diff --git a/pydoll/browser/tab.py b/pydoll/browser/tab.py index 9a80bcbf..2248d045 100644 --- a/pydoll/browser/tab.py +++ b/pydoll/browser/tab.py @@ -1065,7 +1065,10 @@ async def _wait_page_load(self, timeout: int = 300): response: EvaluateResponse = await self._execute_command( RuntimeCommands.evaluate(expression='document.readyState') ) - if response['result']['result']['value'] == 'complete': + if ( + response['result']['result']['value'] + == self._browser.options.page_load_state.value + ): break if asyncio.get_event_loop().time() - start_time > timeout: raise WaitElementTimeout('Page load timed out') diff --git a/pydoll/constants.py b/pydoll/constants.py index d8c876b4..5fcc05f1 100644 --- a/pydoll/constants.py +++ b/pydoll/constants.py @@ -10,6 +10,11 @@ class By(str, Enum): NAME = 'name' +class PageLoadState(str, Enum): + COMPLETE = 'complete' + INTERACTIVE = 'interactive' + + class Scripts: ELEMENT_VISIBLE = """ function() { diff --git a/tests/test_browser/test_browser_options.py b/tests/test_browser/test_browser_options.py index 3e15a45d..4af4e3f1 100644 --- a/tests/test_browser/test_browser_options.py +++ b/tests/test_browser/test_browser_options.py @@ -2,6 +2,7 @@ from pydoll.browser.interfaces import Options as OptionsInterface from pydoll.browser.options import ChromiumOptions as Options +from pydoll.constants import PageLoadState from pydoll.exceptions import ( ArgumentAlreadyExistsInOptions, ArgumentNotFoundInOptions, @@ -31,6 +32,17 @@ def test_set_start_timeout(): assert options.start_timeout == 30 +def test_initial_page_load_state(): + options = Options() + assert options.page_load_state == PageLoadState.COMPLETE + + +def test_set_page_load_state(): + options = Options() + options.page_load_state = PageLoadState.INTERACTIVE + assert options.page_load_state == PageLoadState.INTERACTIVE + + def test_add_argument(): options = Options() options.add_argument('--headless') @@ -225,6 +237,14 @@ def browser_preferences(self): def headless(self): return False + @property + def page_load_state(self): + return PageLoadState.COMPLETE + + @page_load_state.setter + def page_load_state(self, state): + pass + CompleteOptions() def test_set_headless(): From f649b4c29efb00c294904c7b34f513d29c88ddaa Mon Sep 17 00:00:00 2001 From: Thalison Fernandes Date: Sun, 5 Oct 2025 14:52:55 -0300 Subject: [PATCH 2/2] test: add ChromiumOptions to the mock browser instance in tests --- tests/test_browser/test_browser_tab.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_browser/test_browser_tab.py b/tests/test_browser/test_browser_tab.py index d443b085..c1d40a37 100644 --- a/tests/test_browser/test_browser_tab.py +++ b/tests/test_browser/test_browser_tab.py @@ -6,6 +6,7 @@ from unittest.mock import AsyncMock, MagicMock, patch, ANY from pathlib import Path +from pydoll.browser.options import ChromiumOptions from pydoll.protocol.network.types import ResourceType, RequestMethod from pydoll.protocol.fetch.types import RequestStage from pydoll.constants import By @@ -45,6 +46,7 @@ async def mock_browser(): """Mock browser instance.""" browser = MagicMock() browser.close_tab = AsyncMock() + browser.options = ChromiumOptions() return browser