"""Tests for notes CRUD and sync endpoints.""" import sys, os sys.path.insert(0, os.path.dirname(__file__)) import pytest import pytest_asyncio from httpx import AsyncClient from helpers import auth_header, register_and_login @pytest.mark.asyncio async def test_create_note(client: AsyncClient): token, _ = await register_and_login(client) resp = await client.post( "/api/notes", json={ "id": "note-001", "title": "Test Note", "tags": ["tag1", "tag2"], "strokes_json": "[{\"x\":1,\"y\":2}]", }, headers=auth_header(token), ) assert resp.status_code == 201 data = resp.json() assert data["id"] == "note-001" assert data["title"] == "Test Note" assert data["tags"] == ["tag1", "tag2"] @pytest.mark.asyncio async def test_get_note(client: AsyncClient): token, _ = await register_and_login(client) await client.post( "/api/notes", json={"id": "note-002", "title": "Fetch Me", "tags": [], "strokes_json": "[]"}, headers=auth_header(token), ) resp = await client.get("/api/notes/note-002", headers=auth_header(token)) assert resp.status_code == 200 assert resp.json()["title"] == "Fetch Me" @pytest.mark.asyncio async def test_get_note_not_found(client: AsyncClient): token, _ = await register_and_login(client) resp = await client.get("/api/notes/nonexistent", headers=auth_header(token)) assert resp.status_code == 404 @pytest.mark.asyncio async def test_update_note(client: AsyncClient): token, _ = await register_and_login(client) await client.post( "/api/notes", json={"id": "note-003", "title": "Original", "tags": [], "strokes_json": "[]"}, headers=auth_header(token), ) resp = await client.post( "/api/notes", json={"id": "note-003", "title": "Updated", "tags": ["new"], "strokes_json": "[1]"}, headers=auth_header(token), ) assert resp.status_code == 201 assert resp.json()["title"] == "Updated" assert resp.json()["tags"] == ["new"] @pytest.mark.asyncio async def test_delete_note(client: AsyncClient): token, _ = await register_and_login(client) await client.post( "/api/notes", json={"id": "note-004", "title": "Delete Me", "tags": [], "strokes_json": "[]"}, headers=auth_header(token), ) resp = await client.delete("/api/notes/note-004", headers=auth_header(token)) assert resp.status_code == 200 resp = await client.get("/api/notes/note-004", headers=auth_header(token)) assert resp.status_code == 404 @pytest.mark.asyncio async def test_list_notes_with_since(client: AsyncClient): token, _ = await register_and_login(client) await client.post( "/api/notes", json={"id": "note-005", "title": "Old", "tags": [], "strokes_json": "[]"}, headers=auth_header(token), ) resp = await client.get("/api/notes", headers=auth_header(token)) assert resp.status_code == 200 assert len(resp.json()) >= 1 resp = await client.get( "/api/notes?since=2099-01-01T00:00:00+00:00", headers=auth_header(token), ) assert resp.status_code == 200 assert len(resp.json()) == 0 @pytest.mark.asyncio async def test_notes_require_auth(client: AsyncClient): resp = await client.get("/api/notes") assert resp.status_code in (401, 403) # ── Sync ──────────────────────────────────────────────────────────────────── @pytest.mark.asyncio async def test_sync_push(client: AsyncClient): token, _ = await register_and_login(client) resp = await client.post( "/api/sync/push", json={ "notes": [ {"id": "sync-1", "title": "Synced", "tags": [], "strokes_json": "[]", "updated_at": "2024-01-01T00:00:00+00:00"}, {"id": "sync-2", "title": "Also", "tags": ["t"], "strokes_json": "[]", "updated_at": "2024-01-02T00:00:00+00:00"}, ] }, headers=auth_header(token), ) assert resp.status_code == 200 assert resp.json()["synced_count"] == 2 @pytest.mark.asyncio async def test_sync_pull(client: AsyncClient): token, _ = await register_and_login(client) await client.post( "/api/sync/push", json={"notes": [{"id": "pull-1", "title": "Pull Me", "tags": [], "strokes_json": "[]", "updated_at": "2024-06-01T00:00:00+00:00"}]}, headers=auth_header(token), ) resp = await client.post( "/api/sync/pull", json={"since": "2024-01-01T00:00:00+00:00"}, headers=auth_header(token), ) assert resp.status_code == 200 notes = resp.json()["notes"] assert len(notes) >= 1 assert any(n["id"] == "pull-1" for n in notes)