Skip to content
Closed
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dev = [
"pytest>=7.0.0",
"pytest-asyncio",
"pytest-xdist",
"respx>=0.21.0",
"mypy",
"build",
"twine",
Expand All @@ -53,6 +54,9 @@ vercel = ["py.typed"]
testpaths = ["tests"]
addopts = "-q"
asyncio_mode = "auto"
markers = [
"live: requires live API credentials (VERCEL_TOKEN, BLOB_READ_WRITE_TOKEN, etc.)",
]

[tool.mypy]
ignore_missing_imports = true
Expand Down
2 changes: 1 addition & 1 deletion src/vercel/projects/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def update_project(
team_id: str | None = None,
slug: str | None = None,
base_url: str = DEFAULT_API_BASE_URL,
timeout: float = 30.0,
timeout: float = DEFAULT_TIMEOUT,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an actual behavioral change that is intentional. Someone flag if there is a reason why the async version uses DEFAULT_TIMEOUT (which is 60 seconds) and the sync version uses 30 seconds.

) -> dict[str, Any]:
"""Update an existing project by id or name."""
params: dict[str, Any] = {}
Expand Down
Empty file added tests/__init__.py
Empty file.
102 changes: 102 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Shared fixtures for all tests."""

import os
import time
import uuid
from collections.abc import Generator

import pytest


@pytest.fixture
def mock_env_clear(monkeypatch: pytest.MonkeyPatch) -> Generator[None, None, None]:
"""Clear all Vercel-related environment variables for testing.

This ensures tests don't accidentally use real credentials from the environment.
"""
env_vars_to_clear = [
# General Vercel
"VERCEL_TOKEN",
"VERCEL_TEAM_ID",
"VERCEL_PROJECT_ID",
# Blob storage
"BLOB_READ_WRITE_TOKEN",
"BLOB_STORE_ID",
# OIDC
"VERCEL_OIDC_TOKEN",
"VERCEL_OIDC_TOKEN_HEADER",
# Cache
"VERCEL_CACHE_API_TOKEN",
"VERCEL_CACHE_API_URL",
# Functions
"VERCEL_URL",
"VERCEL_ENV",
"VERCEL_REGION",
]
for var in env_vars_to_clear:
monkeypatch.delenv(var, raising=False)
yield


@pytest.fixture
def mock_token() -> str:
"""Mock Vercel API token for testing."""
return "test_token_123456789"


@pytest.fixture
def mock_team_id() -> str:
"""Mock Vercel team ID for testing."""
return "team_test123456789"


@pytest.fixture
def mock_project_id() -> str:
"""Mock Vercel project ID for testing."""
return "prj_test123456789"


@pytest.fixture
def mock_blob_token() -> str:
"""Mock blob storage token for testing."""
return "vercel_blob_rw_test_token_123456789"


@pytest.fixture
def unique_test_name() -> str:
"""Generate a unique test resource name with timestamp."""
timestamp = int(time.time())
unique_id = uuid.uuid4().hex[:8]
return f"vercel-py-test-{timestamp}-{unique_id}"


def has_vercel_credentials() -> bool:
"""Check if Vercel API credentials are available."""
return bool(os.getenv("VERCEL_TOKEN") and os.getenv("VERCEL_TEAM_ID"))


def has_blob_credentials() -> bool:
"""Check if Blob storage credentials are available."""
return bool(os.getenv("BLOB_READ_WRITE_TOKEN"))


def has_sandbox_credentials() -> bool:
"""Check if Sandbox credentials are available."""
return has_vercel_credentials()


# Skip markers for live tests
requires_vercel_credentials = pytest.mark.skipif(
not has_vercel_credentials(),
reason="Requires VERCEL_TOKEN and VERCEL_TEAM_ID environment variables",
)

requires_blob_credentials = pytest.mark.skipif(
not has_blob_credentials(),
reason="Requires BLOB_READ_WRITE_TOKEN environment variable",
)

requires_sandbox_credentials = pytest.mark.skipif(
not has_sandbox_credentials(),
reason="Requires VERCEL_TOKEN and VERCEL_TEAM_ID environment variables for sandbox",
)
Empty file added tests/integration/__init__.py
Empty file.
Loading