Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions src/vip_tests/workbench/exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,10 @@ def rstudio_eval(page: Page, expr: str, timeout: int = 30_000) -> str:
# selecting immediately can miss R and fall back to the (less reliable) Python
# console. Bounded so a genuinely R-less deployment settles quickly.
_POSITRON_R_GRACE_POLLS = 10
# Polls to let .positron-console re-render after activating the Console tab. A
# console hidden behind the Terminal is removed from the DOM on some Positron
# builds, so we activate + briefly poll before concluding no console exists.
_POSITRON_REACTIVATE_POLLS = 3


def ensure_positron_console(page: Page, timeout: int = 45_000) -> bool:
Expand All @@ -302,8 +306,24 @@ def ensure_positron_console(page: Page, timeout: int = 45_000) -> bool:
Returns:
``True`` if a console is running, ``False`` otherwise.
"""
if page.locator(PositronSession.CONSOLE_PANEL).count() > 0:
return True
# One poll budget is shared across every phase below so the total wait is
# bounded by *timeout* rather than a multiple of it.
remaining = max(1, timeout // _POSITRON_POLL_MS)

# A console started earlier may be hidden behind the Terminal tab (a prior
# terminal_run selects it), which removes .positron-console from the DOM on
# some Positron builds. Activate the Console tab first and give the panel a
# moment to re-render, so an existing console is detected instead of being
# missed -- once a session exists its "Start New Console Session" button is
# gone, so a missed console would otherwise look like "no console" and fail.
_activate_positron_console(page)
reactivate = min(remaining, _POSITRON_REACTIVATE_POLLS)
while reactivate > 0:
if page.locator(PositronSession.CONSOLE_PANEL).count() > 0:
return True
page.wait_for_timeout(_POSITRON_POLL_MS)
Comment on lines +320 to +324
reactivate -= 1
remaining -= 1

start = page.locator(_POSITRON_START_BUTTON)
if start.count() == 0:
Expand All @@ -313,10 +333,6 @@ def ensure_positron_console(page: Page, timeout: int = 45_000) -> bool:
except Exception:
return False

# A single poll budget is shared across both phases below so the total wait
# is bounded by *timeout* rather than ~2x it.
remaining = max(1, timeout // _POSITRON_POLL_MS)

# Phase 1: poll the interpreter quickpick — discovery lags the click on a
# cold session (~10s live).
while page.locator(_POSITRON_QUICKPICK_ROW).count() == 0 and remaining > 0:
Expand Down
Loading