mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-04-26 10:41:14 +00:00
Some checks failed
Auto Create GitHub Release on Version Change / check-version-change (push) Waiting to run
Auto Create GitHub Release on Version Change / create-release (push) Blocked by required conditions
Run tests and pre-commit / Run tests and pre-commit hooks (push) Waiting to run
Run tests and pre-commit / Frontend Lint and Build (push) Waiting to run
Publish Fern Docs / run (push) Waiting to run
Build Skyvern SDK and publish to PyPI / check-version-change (push) Waiting to run
Build Skyvern SDK and publish to PyPI / run-ci (push) Blocked by required conditions
Build Skyvern SDK and publish to PyPI / build-sdk (push) Blocked by required conditions
Build Skyvern TS SDK and publish to npm / check-version-change (push) Waiting to run
Build Skyvern TS SDK and publish to npm / build-and-publish-sdk (push) Blocked by required conditions
zizmor / Audit GitHub Actions (push) Has been cancelled
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
144 lines
5 KiB
Python
144 lines
5 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from types import SimpleNamespace
|
|
from unittest.mock import AsyncMock, Mock
|
|
|
|
import pytest
|
|
|
|
import skyvern.cli.mcp_tools.folder as folder_tools
|
|
import skyvern.cli.mcp_tools.workflow as workflow_tools
|
|
from skyvern.client.errors import BadRequestError
|
|
from skyvern.client.raw_client import AsyncRawSkyvern, RawSkyvern
|
|
|
|
|
|
def _fake_folder_response() -> SimpleNamespace:
|
|
now = datetime.now(timezone.utc)
|
|
return SimpleNamespace(
|
|
folder_id="fld_test",
|
|
organization_id="org_test",
|
|
title="Important Workflows",
|
|
description="Folder description",
|
|
workflow_count=3,
|
|
created_at=now,
|
|
modified_at=now,
|
|
)
|
|
|
|
|
|
def _fake_workflow_response() -> SimpleNamespace:
|
|
now = datetime.now(timezone.utc)
|
|
return SimpleNamespace(
|
|
workflow_permanent_id="wpid_test",
|
|
workflow_id="wf_test",
|
|
title="Example Workflow",
|
|
version=1,
|
|
status="published",
|
|
description=None,
|
|
is_saved_task=False,
|
|
folder_id="fld_test",
|
|
created_at=now,
|
|
modified_at=now,
|
|
)
|
|
|
|
|
|
def test_raw_client_delete_folder_raises_not_found_on_empty_404() -> None:
|
|
response = SimpleNamespace(
|
|
status_code=404,
|
|
text="",
|
|
headers={},
|
|
json=Mock(return_value=None),
|
|
)
|
|
client = RawSkyvern(
|
|
client_wrapper=SimpleNamespace(httpx_client=SimpleNamespace(request=Mock(return_value=response)))
|
|
)
|
|
|
|
with pytest.raises(folder_tools.NotFoundError):
|
|
client.delete_folder("fld_missing")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_raw_client_delete_folder_raises_not_found_on_empty_404() -> None:
|
|
response = SimpleNamespace(
|
|
status_code=404,
|
|
text="",
|
|
headers={},
|
|
json=Mock(return_value=None),
|
|
)
|
|
client = AsyncRawSkyvern(
|
|
client_wrapper=SimpleNamespace(httpx_client=SimpleNamespace(request=AsyncMock(return_value=response)))
|
|
)
|
|
|
|
with pytest.raises(folder_tools.NotFoundError):
|
|
await client.delete_folder("fld_missing")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_folder_create_calls_sdk(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
fake_client = SimpleNamespace(create_folder=AsyncMock(return_value=_fake_folder_response()))
|
|
monkeypatch.setattr(folder_tools, "get_skyvern", lambda: fake_client)
|
|
|
|
result = await folder_tools.skyvern_folder_create("Important Workflows", "Folder description")
|
|
|
|
fake_client.create_folder.assert_awaited_once_with(
|
|
title="Important Workflows",
|
|
description="Folder description",
|
|
)
|
|
assert result["ok"] is True
|
|
assert result["data"]["folder_id"] == "fld_test"
|
|
assert result["data"]["title"] == "Important Workflows"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_folder_delete_requires_force() -> None:
|
|
result = await folder_tools.skyvern_folder_delete("fld_test")
|
|
|
|
assert result["ok"] is False
|
|
assert result["error"]["code"] == "INVALID_INPUT"
|
|
assert "force=true" in result["error"]["hint"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_folder_delete_handles_non_dict_sdk_result(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
fake_client = SimpleNamespace(delete_folder=AsyncMock(return_value=["unexpected", "shape"]))
|
|
monkeypatch.setattr(folder_tools, "get_skyvern", lambda: fake_client)
|
|
|
|
result = await folder_tools.skyvern_folder_delete("fld_test", force=True)
|
|
|
|
assert result["ok"] is True
|
|
assert "sdk_equivalent" in result["data"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_workflow_update_folder_calls_sdk(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
fake_client = SimpleNamespace(update_workflow_folder=AsyncMock(return_value=_fake_workflow_response()))
|
|
monkeypatch.setattr(workflow_tools, "get_skyvern", lambda: fake_client)
|
|
|
|
result = await workflow_tools.skyvern_workflow_update_folder("wpid_test", "fld_test")
|
|
|
|
fake_client.update_workflow_folder.assert_awaited_once_with("wpid_test", folder_id="fld_test")
|
|
assert result["ok"] is True
|
|
assert result["data"]["workflow_permanent_id"] == "wpid_test"
|
|
assert result["data"]["folder_id"] == "fld_test"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_workflow_update_folder_rejects_invalid_folder_id() -> None:
|
|
result = await workflow_tools.skyvern_workflow_update_folder("wpid_test", "not_a_folder")
|
|
|
|
assert result["ok"] is False
|
|
assert result["error"]["code"] == "INVALID_INPUT"
|
|
assert "Folder IDs start with fld_" in result["error"]["hint"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_workflow_update_folder_surfaces_bad_request(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
fake_client = SimpleNamespace(
|
|
update_workflow_folder=AsyncMock(side_effect=BadRequestError(body={"detail": "Folder fld_missing not found"}))
|
|
)
|
|
monkeypatch.setattr(workflow_tools, "get_skyvern", lambda: fake_client)
|
|
|
|
result = await workflow_tools.skyvern_workflow_update_folder("wpid_test", "fld_missing")
|
|
|
|
assert result["ok"] is False
|
|
assert result["error"]["code"] == "INVALID_INPUT"
|
|
assert "skyvern_folder_list" in result["error"]["hint"]
|