| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- """Integration tests for External Links API endpoints."""
- import pytest
- from httpx import AsyncClient
- class TestExternalLinksAPI:
- """Integration tests for /api/v1/external-links endpoints."""
- @pytest.fixture
- async def link_factory(self, db_session):
- """Factory to create test external links."""
- _counter = [0]
- async def _create_link(**kwargs):
- from backend.app.models.external_link import ExternalLink
- _counter[0] += 1
- counter = _counter[0]
- defaults = {
- "name": f"Test Link {counter}",
- "url": f"https://example.com/{counter}",
- "icon": "Link",
- "sort_order": counter,
- }
- defaults.update(kwargs)
- link = ExternalLink(**defaults)
- db_session.add(link)
- await db_session.commit()
- await db_session.refresh(link)
- return link
- return _create_link
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_list_external_links_empty(self, async_client: AsyncClient):
- """Verify empty list when no links exist."""
- response = await async_client.get("/api/v1/external-links/")
- assert response.status_code == 200
- assert isinstance(response.json(), list)
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_list_external_links_with_data(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify list returns existing links."""
- await link_factory(name="My Link")
- response = await async_client.get("/api/v1/external-links/")
- assert response.status_code == 200
- data = response.json()
- assert any(link["name"] == "My Link" for link in data)
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_create_external_link(self, async_client: AsyncClient):
- """Verify external link can be created."""
- data = {
- "name": "New Link",
- "url": "https://new-link.example.com",
- "icon": "ExternalLink",
- }
- response = await async_client.post("/api/v1/external-links/", json=data)
- assert response.status_code == 200
- result = response.json()
- assert result["name"] == "New Link"
- assert result["url"] == "https://new-link.example.com"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_get_external_link(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify single link can be retrieved."""
- link = await link_factory(name="Get Test Link")
- response = await async_client.get(f"/api/v1/external-links/{link.id}")
- assert response.status_code == 200
- assert response.json()["name"] == "Get Test Link"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_get_external_link_not_found(self, async_client: AsyncClient):
- """Verify 404 for non-existent link."""
- response = await async_client.get("/api/v1/external-links/9999")
- assert response.status_code == 404
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_update_external_link(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify link can be updated."""
- link = await link_factory(name="Original")
- response = await async_client.patch(
- f"/api/v1/external-links/{link.id}",
- json={"name": "Updated", "url": "https://updated.example.com"}
- )
- assert response.status_code == 200
- result = response.json()
- assert result["name"] == "Updated"
- assert result["url"] == "https://updated.example.com"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_delete_external_link(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify link can be deleted."""
- link = await link_factory()
- response = await async_client.delete(f"/api/v1/external-links/{link.id}")
- assert response.status_code == 200
- # Verify deleted
- response = await async_client.get(f"/api/v1/external-links/{link.id}")
- assert response.status_code == 404
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_reorder_external_links(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify links can be reordered."""
- link1 = await link_factory(name="Link 1")
- link2 = await link_factory(name="Link 2")
- link3 = await link_factory(name="Link 3")
- # Reorder: 3, 1, 2
- response = await async_client.put(
- "/api/v1/external-links/reorder",
- json={"ids": [link3.id, link1.id, link2.id]}
- )
- assert response.status_code == 200
- data = response.json()
- # First link should be link3
- assert data[0]["id"] == link3.id
- assert data[0]["sort_order"] == 0
- class TestExternalLinksIconAPI:
- """Tests for external link icon upload/delete."""
- @pytest.fixture
- async def link_factory(self, db_session):
- """Factory to create test external links."""
- async def _create_link(**kwargs):
- from backend.app.models.external_link import ExternalLink
- defaults = {
- "name": "Icon Test Link",
- "url": "https://example.com",
- "icon": "Link",
- "sort_order": 0,
- }
- defaults.update(kwargs)
- link = ExternalLink(**defaults)
- db_session.add(link)
- await db_session.commit()
- await db_session.refresh(link)
- return link
- return _create_link
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_get_icon_not_set(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify 404 when no custom icon is set."""
- link = await link_factory()
- response = await async_client.get(f"/api/v1/external-links/{link.id}/icon")
- assert response.status_code == 404
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_delete_icon_when_none(
- self, async_client: AsyncClient, link_factory, db_session
- ):
- """Verify deleting non-existent icon succeeds silently."""
- link = await link_factory()
- response = await async_client.delete(f"/api/v1/external-links/{link.id}/icon")
- assert response.status_code == 200
|