Files
hermes-agent/tests/hermes_cli/test_graphical_browser_detection.py
ethernet 9b8ad35ee6 refactor(tests): platforms() fully replaces the linux_only/macos_only/windows_only trio
No shims, one marker system. The full mechanical sweep:

- 165 test files converted: every @pytest.mark.<os>_only decorator and
  pytestmark assignment is now platforms("<os>"). Docstring/comment
  prose mentioning the trio rewritten to the platforms() vocabulary.
- conftest: _OS_MARKS, the legacy skip loop, the double-mark reject for
  the trio, and the selector-tagging shim are deleted. The single
  platforms() gate does all host gating; _reject_contradictory_platform_
  marks replaces the old reject (one platforms() marker per test — a
  module-level pytestmark stacked on a per-test marker is the historic
  skipped-everywhere-green-everywhere failure and stays a hard error).
- pyproject: only the platforms marker is registered.
- list_os_marked_tests.py: rewritten for the single vocabulary — takes
  a platform name (linux/macos/windows), matches quoted platforms(...)
  specs including negated and any-of forms, exits nonzero on empty
  selection. Its test file rewritten to match (bare identifiers must
  not match; the spec must appear inside the string literal).
- tests.yml macOS lane: marker: macos feeds the lister; the pytest
  selection is -m "platforms and not integration" — the marker name is
  the selector, the conftest's per-test host skips are the gate.
- test_os_marker_gating.py rewritten for the new reject (the old file
  tested deleted machinery).
- AGENTS.md / CONTRIBUTING.md updated to the single vocabulary.

Verified: full-tree compile; marker unit tests (36); lister tests;
macOS-lane simulation (21 files, 180 collected / 429 deselected on a
windows host); broad xdist slices through scripts/run_tests.sh
(367 + 1674 passed, zero refactor-attributable failures — the 6 red
tests in the second slice fail identically with the changes stashed).
2026-08-31 17:53:44 -04:00

67 lines
2.3 KiB
Python

"""Tests for `_can_open_graphical_browser()` in hermes_cli.auth.
Guards the fix for the May 2026 report where `hermes auth add xai-oauth`
launched a text-mode browser (w3m) INSIDE the terminal on a headless Linux
box — `_is_remote_session()` only checked SSH/cloud-shell env vars, so a plain
local box with no GUI browser still called `webbrowser.open()`, which resolved
to a console browser and hijacked the TTY.
The helper distinguishes "a real windowed browser will pop up" from "a console
browser will hijack the terminal" so OAuth callsites can fall back to printing
the URL / manual paste instead of auto-opening.
"""
from __future__ import annotations
import webbrowser
import pytest
from hermes_cli.auth import _can_open_graphical_browser
class _FakeController:
def __init__(self, name: str) -> None:
self.name = name
def open(self, *_a, **_kw): # pragma: no cover - never invoked
return True
@pytest.fixture(autouse=True)
def _clean_browser_env(monkeypatch):
"""Each test controls DISPLAY / WAYLAND_DISPLAY / BROWSER explicitly."""
for var in ("DISPLAY", "WAYLAND_DISPLAY", "BROWSER"):
monkeypatch.delenv(var, raising=False)
yield
def _force_resolved_browser(monkeypatch, name: str):
monkeypatch.setattr(webbrowser, "get", lambda *_a, **_kw: _FakeController(name))
@pytest.mark.platforms("linux")
def test_headless_linux_no_display_refuses(monkeypatch):
"""The reported bug: headless Linux, no display server → don't auto-open.
Gated rather than faked: the display-server requirement is the Linux arm
of the helper, and the autouse fixture already strips DISPLAY /
WAYLAND_DISPLAY so a real Linux host reaches it headless.
"""
# Even if a GUI browser somehow resolved, no display means no GUI.
_force_resolved_browser(monkeypatch, "google-chrome")
assert _can_open_graphical_browser() is False
def test_browser_env_pointing_at_console_browser_refuses(monkeypatch):
"""$BROWSER=w3m must refuse even with a display server present.
Host-independent: the $BROWSER console check runs before the helper's
per-platform branch, so this holds on every lane.
"""
monkeypatch.setenv("DISPLAY", ":0")
monkeypatch.setenv("BROWSER", "/usr/bin/w3m")
assert _can_open_graphical_browser() is False