fix(juggler): never enter Responsive Design Mode, and warn about is_mobile

#798 left RDM on for isMobile, as Playwright's Juggler does. RDM matches
no real browser: Firefox for Android never runs it, and under touch
emulation it drops a mouse click's pointer events, which no device does.
Camoufox only has desktop identities, so an is_mobile context was a
desktop UA, platform, fonts and GPU with devtools' mobile mode on top.

Juggler now keeps inRDMPane off for every page, is_mobile included, and
the isMobile plumbing #798 added is gone again. viewport-no-rdm requires
is_mobile=True to keep the platform's scrollbars too.

Both launchers warn instead (warnings.yml is_mobile): on new_page() /
new_context(is_mobile=True) of a Camoufox browser, and on is_mobile
passed to launch_options() for a persistent context. has_touch,
device_scale_factor and viewport keep working without RDM.

Upstream playwright-python skips its isMobile tests on Firefox in
1.61-1.63, so no skiplist entries are needed.

On beta.31 with this Juggler in omni.ja, viewport-no-rdm passes: 12/12 px
of scrollbar with no viewport, with a viewport, and with is_mobile, and a
has_touch click fires pointerdown and pointerup. pythonlib 411 passed;
typescript 584 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jake Writer
2026-09-27 20:09:03 +00:00
co-authored by Claude Opus 5.5
parent 22a9bc581f
commit 8081061156
12 changed files with 156 additions and 20 deletions
+8
View File
@@ -191,3 +191,11 @@ def test_instant_animations_warn_that_they_are_detectable():
with pytest.warns(LeakWarning, match="getComputedTiming"):
launch(config={"instantAnimations": True}, i_know_what_im_doing=False)
def test_is_mobile_warns_that_camoufox_is_desktop_only():
"""A persistent context takes its context options at launch."""
from camoufox._warnings import LeakWarning
with pytest.warns(LeakWarning, match="built for desktops"):
launch(is_mobile=True, i_know_what_im_doing=False)
@@ -388,3 +388,32 @@ class TestStockMediaDefaults:
assert browser.kwargs["forced_colors"] == "active"
# the ones the caller left alone still follow the host
assert browser.kwargs["reduced_motion"] == "no-override"
class TestDesktopOnlyWarning:
"""Camoufox has only desktop identities and Juggler never enters Responsive
Design Mode, so is_mobile on new_page()/new_context() gets a LeakWarning."""
class FakeBrowser:
def new_page(self, **kwargs):
return kwargs
def new_context(self, **kwargs):
return kwargs
def test_is_mobile_warns(self):
from camoufox._warnings import LeakWarning
browser = utils.attach_desktop_only_warning(self.FakeBrowser())
for create in (browser.new_page, browser.new_context):
with pytest.warns(LeakWarning, match="built for desktops"):
assert create(is_mobile=True) == {"is_mobile": True}
def test_a_desktop_context_does_not(self):
import warnings
browser = utils.attach_desktop_only_warning(self.FakeBrowser())
with warnings.catch_warnings():
warnings.simplefilter("error")
browser.new_context(viewport={"width": 800, "height": 600}, is_mobile=False)
browser.new_page()