mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-04-28 03:30:10 +00:00
130 lines
4.1 KiB
Python
130 lines
4.1 KiB
Python
"""End-to-end acceptance tests for Skyvern.local(use_in_memory_db=True).
|
|
|
|
Exercises the full embedded mode path:
|
|
- SQLite in-memory database
|
|
- BackgroundTaskExecutor (default in-process executor)
|
|
- LocalStorage with temp directory (rebuilt during bootstrap)
|
|
- Lifecycle cleanup (engine disposal, client close)
|
|
|
|
Requires OPENAI_API_KEY and Playwright browsers installed.
|
|
Skipped in CI unless the key is available.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from skyvern.forge.sdk.api.llm.models import LLMConfig
|
|
|
|
|
|
def _has_playwright_browser() -> bool:
|
|
"""Check that Playwright's chromium binary exists for the current installed version."""
|
|
try:
|
|
from playwright.sync_api import sync_playwright # noqa: PLC0415
|
|
|
|
with sync_playwright() as p:
|
|
return Path(p.chromium.executable_path).exists()
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
_skip_no_llm_or_browser = pytest.mark.skipif(
|
|
not os.environ.get("OPENAI_API_KEY") or not _has_playwright_browser(),
|
|
reason="Requires OPENAI_API_KEY and Playwright browsers installed (run: playwright install chromium)",
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@_skip_no_llm_or_browser
|
|
async def test_embedded_mode_run_task() -> None:
|
|
"""Path 1: run_task() exercises BackgroundTaskExecutor + polling + full DB lifecycle.
|
|
|
|
Flow: httpx -> ASGITransport -> FastAPI -> BackgroundTaskExecutor ->
|
|
ForgeAgent.execute_step() -> LLM + browser -> artifact save -> task complete
|
|
"""
|
|
from skyvern import Skyvern
|
|
|
|
skyvern = Skyvern.local(
|
|
use_in_memory_db=True,
|
|
llm_config=LLMConfig(
|
|
model_name="gpt-4o-mini",
|
|
required_env_vars=["OPENAI_API_KEY"],
|
|
supports_vision=True,
|
|
add_assistant_prefix=False,
|
|
),
|
|
)
|
|
|
|
try:
|
|
result = await skyvern.run_task(
|
|
prompt="Extract the page title",
|
|
url="https://example.com",
|
|
wait_for_completion=True,
|
|
timeout=120,
|
|
)
|
|
assert result is not None
|
|
assert result.status is not None
|
|
finally:
|
|
await skyvern.aclose()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
@_skip_no_llm_or_browser
|
|
async def test_embedded_mode_page_extract() -> None:
|
|
"""Path 2: page.extract() exercises direct in-process LLM + browser path.
|
|
|
|
Flow: page.extract() -> run_sdk_action() -> LLM call -> result
|
|
Does NOT go through BackgroundTaskExecutor or polling.
|
|
"""
|
|
from skyvern import Skyvern
|
|
|
|
skyvern = Skyvern.local(
|
|
use_in_memory_db=True,
|
|
llm_config=LLMConfig(
|
|
model_name="gpt-4o-mini",
|
|
required_env_vars=["OPENAI_API_KEY"],
|
|
supports_vision=True,
|
|
add_assistant_prefix=False,
|
|
),
|
|
)
|
|
|
|
try:
|
|
browser = await skyvern.launch_local_browser()
|
|
page = await browser.get_working_page()
|
|
await page.goto("https://example.com")
|
|
result = await page.extract("What is the title of this page?")
|
|
assert result is not None
|
|
finally:
|
|
await skyvern.aclose()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_embedded_mode_bootstrap_and_artifacts() -> None:
|
|
"""Verify embedded bootstrap creates SQLite DB, org, token, and redirects artifacts to tempdir.
|
|
|
|
Does NOT require an LLM key — tests the infrastructure, not the LLM path.
|
|
Bootstrap is lazy (happens on first request), so we trigger it via get_workflows().
|
|
"""
|
|
from skyvern import Skyvern
|
|
|
|
skyvern = Skyvern.local(use_in_memory_db=True)
|
|
|
|
try:
|
|
workflows = await skyvern.get_workflows()
|
|
assert workflows is not None
|
|
|
|
embedded_client = getattr(skyvern, "_embedded_client", None)
|
|
assert embedded_client is not None
|
|
|
|
from skyvern.library.embedded_server_factory import EmbeddedClient
|
|
|
|
assert isinstance(embedded_client, EmbeddedClient)
|
|
transport = embedded_client.embedded_transport
|
|
assert transport is not None
|
|
|
|
artifact_dir = getattr(transport, "_artifact_dir", None)
|
|
assert artifact_dir is not None
|
|
assert Path(artifact_dir).exists()
|
|
assert "skyvern-artifacts-" in artifact_dir
|
|
finally:
|
|
await skyvern.aclose()
|