"""Tests for extension distribution endpoints."""
import json
import zipfile
from unittest.mock import MagicMock, patch
import pytest
from httpx import ASGITransport, AsyncClient
from gnexus_creds import api as api_module
def _make_zip(path) -> None:
with zipfile.ZipFile(path, "w") as zf:
zf.writestr("manifest.json", "{}")
@pytest.fixture
def extension_dir(tmp_path):
ext = tmp_path / "extensions"
dist = ext / "dist"
dist.mkdir(parents=True)
chrome = dist / "gnexus-creds-extension-chrome-0.1.0.zip"
firefox = dist / "gnexus-creds-extension-firefox-0.1.0.zip"
for path in (chrome, firefox):
_make_zip(path)
manifest = {
"version": "0.1.0",
"released_at": "2026-08-24T00:00:00Z",
"notes": "test build",
"builds": [
{
"browser": "chrome",
"filename": chrome.name,
"sha256": "a" * 64,
"size": chrome.stat().st_size,
},
{
"browser": "firefox",
"filename": firefox.name,
"sha256": "b" * 64,
"size": firefox.stat().st_size,
},
],
}
(ext / "manifest.json").write_text(json.dumps(manifest))
return ext
@pytest.fixture
def patched_settings(extension_dir):
settings = MagicMock()
settings.extension_dir = str(extension_dir)
with patch.object(api_module, "get_settings", return_value=settings):
yield
@pytest.mark.anyio
async def test_extension_info_lists_builds(app, patched_settings):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
response = await client.get("/api/v1/extension")
assert response.status_code == 200, response.text
data = response.json()
assert data["version"] == "0.1.0"
assert data["notes"] == "test build"
browsers = {build["browser"] for build in data["builds"]}
assert browsers == {"chrome", "firefox"}
for build in data["builds"]:
assert build["download_url"].startswith("/api/v1/extension/download/")
assert build["size"] > 0
assert len(build["sha256"]) == 64
@pytest.mark.anyio
async def test_extension_download_returns_file(app, patched_settings, extension_dir):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
filename = "gnexus-creds-extension-chrome-0.1.0.zip"
response = await client.get(f"/api/v1/extension/download/{filename}")
assert response.status_code == 200, response.text
assert "attachment" in response.headers.get("content-disposition", "")
assert filename in response.headers["content-disposition"]
assert len(response.content) > 0
@pytest.mark.anyio
async def test_extension_download_unknown_returns_404(app, patched_settings):
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
response = await client.get("/api/v1/extension/download/does-not-exist.zip")
assert response.status_code == 404
@pytest.mark.anyio
async def test_extension_info_requires_auth(auth_app, patched_settings):
async with AsyncClient(transport=ASGITransport(app=auth_app), base_url="http://test") as client:
response = await client.get("/api/v1/extension")
assert response.status_code == 401