11 tests passing (7 shares + 4 audit), 309 total, 0 failures. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.5 KiB
plan, title, wave, depends_on, phase, requirements_addressed, files_modified, autonomous
| plan | title | wave | depends_on | phase | requirements_addressed | files_modified | autonomous | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 06.1-01 | Promote test_shares.py stubs to real tests (SHARE-01..05) | 1 | 6.1 |
|
|
true |
Plan 06.1-01 — Promote test_shares.py stubs to real tests
Objective
The backend shares API (api/shares.py) is fully implemented (POST /api/shares, GET /api/shares, GET /api/shares/received, DELETE /api/shares/{id}) but test_shares.py contains only 7 xfail stubs that call pytest.xfail("not implemented yet"). This plan replaces every stub with a real test that asserts correct behaviour.
Context
- Backend implementation:
backend/api/shares.py— fully implemented in Phase 4 Plan 04-04 - Frontend implementation:
frontend/src/views/SharedView.vue+frontend/src/components/layout/AppSidebar.vue— both complete - Test stubs:
backend/tests/test_shares.py— 7 tests all callpytest.xfail("not implemented yet") - Test infrastructure:
backend/tests/conftest.pyprovidesasync_client,auth_user,admin_user,db_session
The shares tests need a second user. The existing auth_user fixture creates one user per test. Sharing requires a sharer and a recipient. A second_auth_user fixture must be added to conftest.py.
Tasks
Task 1 — Add second_auth_user fixture to conftest.py
<read_first>
- backend/tests/conftest.py — read the full
auth_userfixture (lines 186-226) to copy the exact pattern </read_first>
<acceptance_criteria>
conftest.pycontainsasync def second_auth_user(db_session: AsyncSession)decorated with@pytest_asyncio.fixture- The fixture handle prefix is
user2_(distinct fromtestuser_in auth_user) - No duplicate imports — reuse existing imports at the top of conftest.py </acceptance_criteria>
Task 2 — Implement real tests in test_shares.py
Replace all 7 stub bodies in backend/tests/test_shares.py. Each stub currently calls pytest.xfail("not implemented yet"). Replace the content of each test and add the second_auth_user parameter where two users are needed. Remove the import os (unused) and add the necessary imports.
<read_first>
- backend/tests/test_shares.py — full file (stubs to replace)
- backend/api/shares.py — endpoint request/response shapes
- backend/db/models.py — Document and Share model fields (lines 162-263)
- backend/tests/test_documents.py — pattern for creating Document ORM rows directly (lines 55-75) </read_first>
from __future__ import annotations
import uuid as _uuid
import pytest
import pytest_asyncio
Add a module-level helper async def _make_doc(db_session, owner_user) that creates and commits an uploaded Document row owned by owner_user["user"] — same pattern as test_documents.py: insert Document(id=..., user_id=owner_user["user"].id, filename="test.txt", object_key=f"...", size_bytes=1000, status="uploaded") using db_session.add + await db_session.commit(). Returns the str(doc_id).
Then implement each test without any @pytest.mark.xfail decorator (remove them all):
test_share_success(async_client, auth_user, second_auth_user, db_session)
- Create a doc owned by auth_user via
_make_doc - POST /api/shares with
{"document_id": doc_id, "recipient_handle": second_auth_user["user"].handle} - Assert response status 201
- Assert response body contains
"id","document_id"== doc_id,"recipient_id"== str(second_auth_user["user"].id) - GET /api/shares/received with second_auth_user headers
- Assert response 200 and the doc appears in items
test_share_handle_not_found(async_client, auth_user, db_session)
- Create a doc owned by auth_user
- POST /api/shares with
{"document_id": doc_id, "recipient_handle": "nonexistent_handle_xyz"} - Assert status 404
test_shared_with_me(async_client, auth_user, second_auth_user, db_session)
- Create a doc owned by auth_user
- POST /api/shares to share with second_auth_user
- GET /api/shares/received with second_auth_user headers
- Assert status 200
- Assert items list has at least one entry
- Assert the first item has keys: "id", "filename", "content_type", "size_bytes", "created_at", "owner_handle"
- Assert "extracted_text" is NOT a key in any item (T-04-04-03)
- Assert item["owner_handle"] == auth_user["user"].handle
test_share_no_quota_impact(async_client, auth_user, second_auth_user, db_session)
- Ensure second_auth_user has a Quota row with used_bytes=0 (the fixture already does this)
- Create doc owned by auth_user, share with second_auth_user
- GET /api/auth/me/quota with second_auth_user headers
- Assert status 200
- Assert quota["used_bytes"] == 0 (sharing does not charge recipient quota — T-04-04-04)
test_revoke_share(async_client, auth_user, second_auth_user, db_session)
- Create doc, share with second_auth_user, capture share id from 201 response
- DELETE /api/shares/{share_id} with auth_user headers
- Assert 204
- GET /api/shares/received with second_auth_user headers
- Assert the revoked doc no longer appears in items
test_share_revoke_wrong_owner_404(async_client, auth_user, second_auth_user, db_session)
- Create doc, share with second_auth_user, capture share id
- DELETE /api/shares/{share_id} with second_auth_user headers (recipient, NOT owner)
- Assert 404 (IDOR protection: 404, not 403 — T-04-04-02)
test_share_duplicate(async_client, auth_user, second_auth_user, db_session)
- Create doc, share with second_auth_user (first share, 201)
- POST /api/shares with same doc_id + same recipient_handle again
- Assert 409
<acceptance_criteria>
test_shares.pyhas zeropytest.xfailcalls — every test has real assertionstest_shares.pyhas zero@pytest.mark.xfaildecoratorsimport osis removed (was unused)- Every test function has the
@pytest.mark.asynciodecorator OR the file haspytestmark = pytest.mark.asyncioat the top - Running
docker compose exec backend python -m pytest tests/test_shares.py -vshows 7 PASSED (no XFAIL, no XPASS) test_share_no_quota_impactassertsused_bytes == 0for recipienttest_shared_with_measserts"extracted_text" not in itemfor each item in the responsetest_share_revoke_wrong_owner_404asserts status code 404 </acceptance_criteria>
Verification
docker compose exec backend python -m pytest tests/test_shares.py -v
Expected: 7 passed, 0 failed, 0 xfailed, 0 xpassed.
Must-haves
- No test uses
pytest.xfail("not implemented yet")— all 7 stubs replaced with real assertions second_auth_userfixture creates a user with quota row and valid JWT, same pattern asauth_usertest_share_no_quota_impactproves SHARE-02 quota isolation: recipient quota unchanged after sharetest_shared_with_meproves SHARE-02 visibility: recipient sees doc in /receivedtest_share_revoke_wrong_owner_404proves IDOR protection is tested