Files
2026-07-16 23:28:30 +02:00

63 lines
2.6 KiB
Python

"""
Debug/test content fetcher.
Does NOT fetch anything - it echoes the resolved-and-injected browser state (backend name +
FetcherConfig) as JSON into `self.content`. That lets pytest exercise the *entire* browser-config
pipeline end-to-end with a real watch check - resolve_content_fetcher -> engine selection ->
FetcherConfig injection -> fetch - and assert on the stored snapshot, all without a real browser.
Registered as a built-in fetcher but hidden from the UI browser lists (name prefixed 'html_debug').
"""
import json
from changedetectionio.content_fetchers.base import Fetcher, FetcherCapabilities
class fetcher(Fetcher):
fetcher_description = "Debug test browser (echoes resolved browser config)"
# Advertise every capability so all FetcherConfig fields are exercisable through it.
supports_browser_steps = True
supports_screenshots = True
supports_xpath_element_data = True
supports_request_blocking = True
supports_browser_type = True
supports_delete_created_files = True
async def run(self,
url=None,
request_headers=None,
request_body=None,
request_method=None,
**kwargs):
bc = getattr(self, 'browser_config', None)
payload = {
'debug_test_browser': True,
'backend_name': getattr(self, 'backend_name', None),
# The resolved sub-browser engine (firefox/chromium/webkit) when the config sets one.
'browser_type': (getattr(bc, 'browser_type', None) if bc is not None else None),
'url': url,
# Every configurable FetcherConfig field (the full resolved config)...
'browser_config': bc.model_dump() if (bc is not None and hasattr(bc, 'model_dump')) else bc,
# ...and every capability (supports_*) this fetcher advertises.
'capabilities': FetcherCapabilities.from_fetcher(type(self)).model_dump(),
'request_headers': {k: v for k, v in (request_headers or {}).items()},
}
self.content = json.dumps(payload, indent=2, sort_keys=True, default=str)
self.raw_content = self.content.encode('utf-8')
self.status_code = 200
self.headers = {'content-type': 'application/json'}
self.screenshot = None
self.xpath_data = {'xpath_data': [], 'browser_width': 0}
self.instock_data = None
class DebugTestBrowserFetcherPlugin:
"""Registers the debug test fetcher as a built-in plugin."""
def register_content_fetcher(self):
return ('html_debug_test_browser', fetcher)
debug_test_browser_plugin = DebugTestBrowserFetcherPlugin()