Add is_cdp flag and CDP robustness improvements#97
Add is_cdp flag and CDP robustness improvements#97wwakabobik wants to merge 6 commits intoCustomEnv:masterfrom
Conversation
d57fc68 to
24661a6
Compare
Problem: MOPS requires users to manually create driver objects when connecting to remote browsers via Chrome DevTools Protocol (CDP). This involves boilerplate code for lifecycle management and cleanup. Use cases: - Testing Electron apps on remote machines via CDP + SSH tunnel - Connecting to cloud browser services (BrowserStack, Sauce Labs) - Attaching to an already-running browser instance for debugging - Testing CEF-based or WebView2 applications Solution: Add a factory classmethod DriverWrapper.connect_cdp(endpoint_url) that handles the full lifecycle. Supports both Playwright and Selenium engines via the engine parameter (default: "playwright"). Playwright engine: Starts Playwright, connects via chromium.connect_over_cdp, wraps the resulting page. Playwright instance is stopped on quit(). Selenium engine: Creates Chrome WebDriver with debugger_address option pointing to the CDP endpoint. URL is parsed via urllib.parse for robustness. Architectural changes: - DriverWrapper.is_cdp flag: identifies CDP-connected wrappers - PlayDriver.quit(): tracing.stop() skipped for CDP contexts - CoreDriver.quit(): try/except guarded by is_cdp only (non-CDP Selenium quit behavior preserved) - PlayDriver.get_inner_window_size(): null-safe for CDP default viewport Version bump: 3.3.1 -> 3.4.0 Documentation: - Getting Started: CDP section with both engine examples + limitations - Index: CDP listed in key features - DriverWrapper overview: CDP mentioned in description and status attrs - CHANGELOG: v3.4.0 entry Tests: 13 unit tests covering both engines, is_cdp flag, URL parsing, parameters, cleanup, sessions, and compatibility Made-with: Cursor
24661a6 to
54c88fd
Compare
Made-with: Cursor
… feature/connect-cdp
Resolve conflicts in mops/__init__.py and CHANGELOG.md: - Version set to 3.4.3 (CDP feature on top of upstream 3.4.2) - CHANGELOG: upstream 3.4.0-3.4.2 entries preserved, CDP entry renumbered to 3.4.3 Made-with: Cursor
|
@wwakabobik thanks for the contribution, but this PR cannot be accepted in its current state as it violates the wrapper pattern rules. DriverWrapper should not be responsible for creating new driver connections. The driver setup should be handled on the user's project side instead, since there can be a wide variety of settings and capabilities involved — custom browser options, capability configs, environment-specific flags, and so on. The wrapper's sole responsibility is to wrap an already-initialized driver, not to manage its creation or lifecycle bootstrapping even with cdp connection. That said, the is_cdp flag and the related robustness changes in quit() and get_inner_window_size() look genuinely useful and are worth keeping |
Maintainer feedback: DriverWrapper should not create driver connections, only wrap already-initialized drivers. The connect_cdp factory violated the wrapper pattern — driver setup with custom options/capabilities belongs on the user's project side. Removed: - connect_cdp(), _connect_cdp_playwright(), _connect_cdp_selenium() - sync_playwright import and _playwright_instance cleanup - CDP connection docs from getting_started, index, driver_wrapper overview Kept (accepted by maintainer): - is_cdp flag on DriverWrapper and ABC - PlayDriver.quit() tracing skip + error guards for CDP - CoreDriver.quit() error guard for CDP - PlayDriver.get_inner_window_size() null-safe viewport Tests: replaced test_connect_cdp.py (14 factory tests) with test_cdp_robustness.py (11 tests covering is_cdp, quit behavior, viewport null-safety). All 390 static + 15 ABC tests pass. Made-with: Cursor
|
Updated ro conform changes proposed/approved by maintainer. |
Summary
DriverWrapper.is_cdpflag to identify CDP-connected driver instancesquit()across Playwright and Selenium drivers for CDP robustnessProblem
When users connect to a remote browser via CDP (e.g., Electron app with
--remote-debugging-port=9222) and wrap it in aDriverWrapper, several runtime issues occur:PlayDriver.quit()callstracing.stop()which fails because tracing was never started on pre-existing CDP contextsPlayDriver.quit()callspage.close()/context.close()which can throwPlaywrightErrorfor externally-managed browsersCoreDriver.quit()callsdriver.quit()which can throwWebDriverExceptionfor externally-managed browsersPlayDriver.get_inner_window_size()crashes whenviewport_sizeisNone(default for CDP pages without explicit viewport)These are runtime bugs that every project connecting via CDP would hit independently.
Solution
A new
is_cdpboolean flag onDriverWrapper(defaultFalse) that users set after creating their CDP connection:Driver creation stays on the user's project side (per wrapper-pattern rules). MOPS only provides the robustness layer via
is_cdp.Robustness changes
PlayDriver.quit()tracing.stop()skipped whenis_cdp=True;page.close()andcontext.close()wrapped intry/except PlaywrightErrorfor CDP onlyCoreDriver.quit()driver.quit()wrapped intry/except SeleniumWebDriverExceptionfor CDP onlyPlayDriver.get_inner_window_size()Size(0, 0)whenviewport_sizeisNoneNon-CDP behavior is completely unchanged — error suppression only applies when
is_cdp=True.Files Changed
mops/__init__.pymops/base/driver_wrapper.pyis_cdpflagmops/abstraction/driver_wrapper_abc.pyis_cdpattribute in ABCmops/playwright/play_driver.pyquit(): tracing skip + try/except for CDP;get_inner_window_size()null-safemops/selenium/core/core_driver.pyquit(): try/except guarded byis_cdpdocs/source/driver_wrapper/index.mdis_cdpin status attributesCHANGELOG.mdtests/static_tests/unit/test_cdp_robustness.pyBackward Compatibility
Purely additive — no existing attributes, methods, or signatures change.
is_cdpdefaults toFalse.PlayDriver.quit()andCoreDriver.quit()changes only add safety guards that activate whenis_cdp=True.Test Plan
is_cdpflag tests: default False (Playwright/Selenium), set True (Playwright/Selenium)