mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-04-28 11:40:32 +00:00
133 lines
4.6 KiB
Python
133 lines
4.6 KiB
Python
"""
|
|
Tests for RealBrowserManager cache behavior (regression coverage for PR #9020).
|
|
|
|
PR #9020 introduced a regression where the self.pages cache check was gated
|
|
behind `if not browser_session_id:`, causing PBS workflow runs to skip the cache
|
|
on every call and re-invoke navigate_to_url() on every step.
|
|
"""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
from skyvern.webeye.real_browser_manager import RealBrowserManager
|
|
|
|
|
|
def make_workflow_run(
|
|
workflow_run_id: str,
|
|
parent_workflow_run_id: str | None = None,
|
|
organization_id: str = "org_test",
|
|
browser_profile_id: str | None = None,
|
|
) -> MagicMock:
|
|
wfr = MagicMock()
|
|
wfr.workflow_run_id = workflow_run_id
|
|
wfr.parent_workflow_run_id = parent_workflow_run_id
|
|
wfr.organization_id = organization_id
|
|
wfr.browser_profile_id = browser_profile_id
|
|
wfr.proxy_location = None
|
|
wfr.extra_http_headers = None
|
|
wfr.browser_address = None
|
|
return wfr
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_pbs_workflow_run_cache_hit_on_second_call() -> None:
|
|
"""PBS runs must hit the cache on subsequent calls and NOT re-enter the PBS branch."""
|
|
manager = RealBrowserManager()
|
|
cached_state = MagicMock()
|
|
manager.pages["wfr_child"] = cached_state
|
|
|
|
workflow_run = make_workflow_run("wfr_child")
|
|
with patch("skyvern.webeye.real_browser_manager.app") as mock_app:
|
|
result = await manager.get_or_create_for_workflow_run(
|
|
workflow_run=workflow_run,
|
|
url="https://example.com",
|
|
browser_session_id="bs_123",
|
|
)
|
|
mock_app.PERSISTENT_SESSIONS_MANAGER.get_browser_state.assert_not_called()
|
|
|
|
assert result is cached_state
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_pbs_workflow_run_does_not_inherit_parent_browser() -> None:
|
|
"""Child PBS runs must NOT inherit the parent's browser on the first call."""
|
|
manager = RealBrowserManager()
|
|
parent_state = MagicMock()
|
|
manager.pages["wfr_parent"] = parent_state
|
|
|
|
workflow_run = make_workflow_run("wfr_child", parent_workflow_run_id="wfr_parent")
|
|
|
|
pbs_state = MagicMock()
|
|
pbs_state.get_working_page = AsyncMock(return_value=None)
|
|
pbs_state.get_or_create_page = AsyncMock()
|
|
|
|
with patch("skyvern.webeye.real_browser_manager.app") as mock_app:
|
|
mock_app.PERSISTENT_SESSIONS_MANAGER.get_browser_state = AsyncMock(return_value=pbs_state)
|
|
mock_app.PERSISTENT_SESSIONS_MANAGER.set_browser_state = AsyncMock()
|
|
|
|
result = await manager.get_or_create_for_workflow_run(
|
|
workflow_run=workflow_run,
|
|
url="https://example.com",
|
|
browser_session_id="bs_123",
|
|
)
|
|
|
|
# Must use the PBS session, not the parent's browser
|
|
assert result is pbs_state
|
|
assert result is not parent_state
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_pbs_workflow_run_returns_own_cache_not_parent() -> None:
|
|
"""When both child and parent are cached, PBS must return the child's own entry."""
|
|
manager = RealBrowserManager()
|
|
child_state = MagicMock()
|
|
manager.pages["wfr_child"] = child_state
|
|
manager.pages["wfr_parent"] = MagicMock()
|
|
|
|
workflow_run = make_workflow_run("wfr_child", parent_workflow_run_id="wfr_parent")
|
|
result = await manager.get_or_create_for_workflow_run(
|
|
workflow_run=workflow_run,
|
|
url="https://example.com",
|
|
browser_session_id="bs_123",
|
|
)
|
|
|
|
assert result is child_state
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_non_pbs_workflow_run_cache_hit_on_second_call() -> None:
|
|
"""Non-PBS runs must also hit the early cache check on subsequent calls."""
|
|
manager = RealBrowserManager()
|
|
cached_state = MagicMock()
|
|
manager.pages["wfr_child"] = cached_state
|
|
|
|
workflow_run = make_workflow_run("wfr_child", parent_workflow_run_id="wfr_parent")
|
|
result = await manager.get_or_create_for_workflow_run(
|
|
workflow_run=workflow_run,
|
|
url=None,
|
|
browser_session_id=None,
|
|
)
|
|
|
|
assert result is cached_state
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_non_pbs_workflow_run_inherits_parent_browser() -> None:
|
|
"""Non-PBS child runs must still inherit the parent's browser when no browser_session_id."""
|
|
manager = RealBrowserManager()
|
|
parent_state = MagicMock()
|
|
manager.pages["wfr_parent"] = parent_state
|
|
|
|
workflow_run = make_workflow_run("wfr_child", parent_workflow_run_id="wfr_parent")
|
|
|
|
result = await manager.get_or_create_for_workflow_run(
|
|
workflow_run=workflow_run,
|
|
url=None,
|
|
browser_session_id=None,
|
|
)
|
|
|
|
assert result is parent_state
|
|
# Both entries should be synced
|
|
assert manager.pages["wfr_child"] is parent_state
|
|
assert manager.pages["wfr_parent"] is parent_state
|