"""Tests for post routes.""" import io from unittest.mock import patch import pytest from fastapi.testclient import TestClient def test_create_post_success(client: TestClient, two_users: dict): """Test successful post creation.""" token = two_users["user1_token"] # Create a fake image fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "My first post!"}, headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == 201 data = response.json() assert data["caption"] == "My first post!" assert data["user_id"] is not None assert data["likes_count"] == 0 assert data["dislikes_count"] == 0 assert data["comments_count"] == 0 def test_create_post_unauthorized(client: TestClient): """Test creating post without authentication.""" fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "My first post!"}, ) assert response.status_code == 401 # No credentials def test_create_post_invalid_file_type(client: TestClient, two_users: dict): """Test creating post with invalid file type.""" token = two_users["user1_token"] fake_file = io.BytesIO(b"fake content") fake_file.name = "test.txt" response = client.post( "/posts", files={"image": ("test.txt", fake_file, "text/plain")}, data={"caption": "Invalid file"}, headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == 400 assert "File type not allowed" in response.json()["detail"] def test_get_posts_empty(client: TestClient): """Test getting posts when database is empty.""" response = client.get("/posts") assert response.status_code == 200 assert response.json() == [] def test_get_posts(client: TestClient, two_users: dict): """Test getting posts.""" token = two_users["user1_token"] # Create a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Test post"}, headers={"Authorization": f"Bearer {token}"}, ) response = client.get("/posts") assert response.status_code == 200 posts = response.json() assert len(posts) == 1 assert posts[0]["caption"] == "Test post" def test_get_single_post(client: TestClient, two_users: dict): """Test getting a single post.""" token = two_users["user1_token"] # Create a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Single post test"}, headers={"Authorization": f"Bearer {token}"}, ) post_id = create_response.json()["id"] response = client.get(f"/posts/{post_id}") assert response.status_code == 200 assert response.json()["caption"] == "Single post test" def test_get_nonexistent_post(client: TestClient): """Test getting a post that doesn't exist.""" response = client.get("/posts/9999") assert response.status_code == 404 def test_delete_post_by_owner(client: TestClient, two_users: dict): """Test deleting own post.""" token = two_users["user1_token"] # Create a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "To be deleted"}, headers={"Authorization": f"Bearer {token}"}, ) post_id = create_response.json()["id"] # Delete the post response = client.delete( f"/posts/{post_id}", headers={"Authorization": f"Bearer {token}"}, ) assert response.status_code == 204 # Verify it's deleted response = client.get(f"/posts/{post_id}") assert response.status_code == 404 def test_delete_post_by_non_owner(client: TestClient, two_users: dict): """Test trying to delete someone else's post.""" token1 = two_users["user1_token"] token2 = two_users["user2_token"] # User 1 creates a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "User 1's post"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # User 2 tries to delete it response = client.delete( f"/posts/{post_id}", headers={"Authorization": f"Bearer {token2}"}, ) assert response.status_code == 403 assert "You can only delete your own posts" in response.json()["detail"] def test_like_post(client: TestClient, two_users: dict): """Test liking a post.""" token1 = two_users["user1_token"] # User 1 creates a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Like test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # Like the post response = client.post( f"/posts/{post_id}/like", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 201 assert response.json()["message"] == "Post liked" # Verify like count response = client.get(f"/posts/{post_id}") assert response.json()["likes_count"] == 1 def test_unlike_post(client: TestClient, two_users: dict): """Test removing a like from a post.""" token1 = two_users["user1_token"] # User 1 creates a post and likes it fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Unlike test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] client.post( f"/posts/{post_id}/like", headers={"Authorization": f"Bearer {token1}"}, ) # Unlike the post response = client.delete( f"/posts/{post_id}/like", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 200 assert response.json()["message"] == "Like removed" # Verify like count response = client.get(f"/posts/{post_id}") assert response.json()["likes_count"] == 0 def test_dislike_post(client: TestClient, two_users: dict): """Test disliking a post.""" token1 = two_users["user1_token"] # User 1 creates a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Dislike test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # Dislike the post response = client.post( f"/posts/{post_id}/dislike", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 201 assert response.json()["message"] == "Post disliked" # Verify dislike count response = client.get(f"/posts/{post_id}") assert response.json()["dislikes_count"] == 1 def test_like_and_dislike_mutually_exclusive(client: TestClient, two_users: dict): """Test that like and dislike are mutually exclusive.""" token1 = two_users["user1_token"] # User 1 creates a post fake_image = io.BytesIO(b"fake image content") fake_image.name = "test.jpg" create_response = client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Mutual exclusion test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # Like the post client.post( f"/posts/{post_id}/like", headers={"Authorization": f"Bearer {token1}"}, ) # Dislike the post (should replace like) response = client.post( f"/posts/{post_id}/dislike", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 201 # Verify: no likes, 1 dislike response = client.get(f"/posts/{post_id}") data = response.json() assert data["likes_count"] == 0 assert data["dislikes_count"] == 1