PunimTag Web Application - Major Feature Release #1
@ -5,8 +5,8 @@ SQLAlchemy==2.0.36
|
||||
psycopg2-binary==2.9.9
|
||||
redis==5.0.8
|
||||
rq==1.16.2
|
||||
python-jose[cryptography]==3.3.0
|
||||
python-multipart==0.0.9
|
||||
python-jose[cryptography]>=3.4.0
|
||||
python-multipart>=0.0.18
|
||||
python-dotenv==1.0.0
|
||||
bcrypt==4.1.2
|
||||
# Testing Dependencies
|
||||
|
||||
@ -29,6 +29,11 @@ class TestPhotoSearch:
|
||||
# Link face to person
|
||||
test_face.person_id = test_person.id
|
||||
test_db_session.commit()
|
||||
test_db_session.refresh(test_face)
|
||||
|
||||
# Verify the link was created
|
||||
assert test_face.person_id == test_person.id
|
||||
assert test_face.photo_id == test_photo.id
|
||||
|
||||
response = test_client.get(
|
||||
"/api/v1/photos",
|
||||
@ -40,8 +45,11 @@ class TestPhotoSearch:
|
||||
data = response.json()
|
||||
assert "items" in data
|
||||
assert "total" in data
|
||||
# Search may return results if person name matches
|
||||
# Note: search does partial matching on first_name, last_name, etc.
|
||||
# With test_person.first_name="John" and face linked, we should find results
|
||||
assert len(data["items"]) > 0
|
||||
# Verify the photo is in the results
|
||||
photo_ids = [item["id"] for item in data["items"]]
|
||||
assert test_photo.id in photo_ids
|
||||
|
||||
def test_search_photos_by_name_without_person_name(
|
||||
self,
|
||||
@ -306,15 +314,15 @@ class TestPhotoFavorites:
|
||||
):
|
||||
"""Verify bulk add operation."""
|
||||
response = test_client.post(
|
||||
"/api/v1/photos/favorites/bulk-add",
|
||||
"/api/v1/photos/bulk-add-favorites",
|
||||
headers=auth_headers,
|
||||
json={"photo_ids": [test_photo.id, test_photo_2.id]},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["added"] >= 0
|
||||
assert data["already_favorites"] >= 0
|
||||
assert data["added_count"] >= 0
|
||||
assert data["already_favorite_count"] >= 0
|
||||
|
||||
def test_bulk_remove_favorites_success(
|
||||
self,
|
||||
@ -333,14 +341,14 @@ class TestPhotoFavorites:
|
||||
test_db_session.commit()
|
||||
|
||||
response = test_client.post(
|
||||
"/api/v1/photos/favorites/bulk-remove",
|
||||
"/api/v1/photos/bulk-remove-favorites",
|
||||
headers=auth_headers,
|
||||
json={"photo_ids": [test_photo.id]},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["removed"] >= 0
|
||||
assert data["removed_count"] >= 0
|
||||
|
||||
|
||||
class TestPhotoRetrieval:
|
||||
@ -403,6 +411,7 @@ class TestPhotoDeletion:
|
||||
test_client: TestClient,
|
||||
regular_auth_headers: dict,
|
||||
test_photo: "Photo",
|
||||
admin_user, # Ensure an admin exists to prevent bootstrap
|
||||
):
|
||||
"""Verify 403 for non-admin users."""
|
||||
response = test_client.post(
|
||||
|
||||
@ -63,7 +63,7 @@ class TestTagCRUD:
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["tag"] == "new-tag"
|
||||
assert data["tag_name"] == "new-tag"
|
||||
assert "id" in data
|
||||
|
||||
def test_create_tag_duplicate(
|
||||
@ -89,7 +89,7 @@ class TestTagCRUD:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["id"] == tag.id
|
||||
assert data["tag"] == "duplicate-tag"
|
||||
assert data["tag_name"] == "duplicate-tag"
|
||||
|
||||
def test_create_tag_strips_whitespace(
|
||||
self,
|
||||
@ -104,7 +104,7 @@ class TestTagCRUD:
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
# Tag should be trimmed
|
||||
assert "whitespace-tag" in data["tag"]
|
||||
assert "whitespace-tag" in data["tag_name"]
|
||||
|
||||
def test_update_tag_success(
|
||||
self,
|
||||
@ -126,7 +126,7 @@ class TestTagCRUD:
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["tag"] == "new-name"
|
||||
assert data["tag_name"] == "new-name"
|
||||
|
||||
def test_update_tag_not_found(
|
||||
self,
|
||||
|
||||
@ -36,6 +36,7 @@ class TestUserListing:
|
||||
self,
|
||||
test_client: TestClient,
|
||||
regular_auth_headers: dict,
|
||||
admin_user, # Ensure an admin exists to prevent bootstrap
|
||||
):
|
||||
"""Verify 403 for non-admin users."""
|
||||
response = test_client.get(
|
||||
@ -168,6 +169,7 @@ class TestUserCRUD:
|
||||
f"/api/v1/users/{admin_user.id}",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"email": admin_user.email,
|
||||
"full_name": "Updated Name",
|
||||
},
|
||||
)
|
||||
@ -233,9 +235,14 @@ class TestUserActivation:
|
||||
inactive_user: "User",
|
||||
):
|
||||
"""Verify user activation."""
|
||||
response = test_client.post(
|
||||
f"/api/v1/users/{inactive_user.id}/activate",
|
||||
response = test_client.put(
|
||||
f"/api/v1/users/{inactive_user.id}",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"email": inactive_user.email,
|
||||
"full_name": inactive_user.full_name or inactive_user.username,
|
||||
"is_active": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@ -249,9 +256,14 @@ class TestUserActivation:
|
||||
regular_user: "User",
|
||||
):
|
||||
"""Verify user deactivation."""
|
||||
response = test_client.post(
|
||||
f"/api/v1/users/{regular_user.id}/deactivate",
|
||||
response = test_client.put(
|
||||
f"/api/v1/users/{regular_user.id}",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"email": regular_user.email,
|
||||
"full_name": regular_user.full_name or regular_user.username,
|
||||
"is_active": False,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
@ -264,9 +276,14 @@ class TestUserActivation:
|
||||
auth_headers: dict,
|
||||
):
|
||||
"""Verify 404 handling."""
|
||||
response = test_client.post(
|
||||
"/api/v1/users/99999/activate",
|
||||
response = test_client.put(
|
||||
"/api/v1/users/99999",
|
||||
headers=auth_headers,
|
||||
json={
|
||||
"email": "nonexistent@example.com",
|
||||
"full_name": "Nonexistent User",
|
||||
"is_active": True,
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user