"""Tests for social features: users, follows, comments.""" import io import pytest from fastapi.testclient import TestClient def test_get_user_profile(client: TestClient, two_users: dict): """Test getting a user profile.""" token1 = two_users["user1_token"] # Get user ID from token (simplified - in real app would decode) # Let's create a post first to get the user 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 {token1}"}, ) # For now, just test that user endpoint exists and works # The actual user ID would need to be extracted from the token response = client.get("/users/1") assert response.status_code == 200 data = response.json() assert data["username"] == "user1" def test_get_user_stats(client: TestClient, two_users: dict): """Test getting user statistics.""" token1 = 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": "Stats test"}, headers={"Authorization": f"Bearer {token1}"}, ) # User 2 follows User 1 client.post( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) response = client.get("/users/1/stats") assert response.status_code == 200 data = response.json() assert data["posts_count"] == 1 assert data["followers_count"] == 1 assert data["following_count"] == 0 def test_follow_user(client: TestClient, two_users: dict): """Test following a user.""" # User 2 follows User 1 response = client.post( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) assert response.status_code == 201 assert response.json()["message"] == "Successfully followed user" def test_follow_self(client: TestClient, two_users: dict): """Test that you cannot follow yourself.""" response = client.post( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user1_token']}"}, ) assert response.status_code == 400 assert "You cannot follow yourself" in response.json()["detail"] def test_follow_already_following(client: TestClient, two_users: dict): """Test following someone you already follow.""" # User 2 follows User 1 client.post( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) # Try to follow again response = client.post( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) assert response.status_code == 400 assert "You already follow this user" in response.json()["detail"] def test_unfollow_user(client: TestClient, two_users: dict): """Test unfollowing a user.""" token2 = two_users["user2_token"] # User 2 follows User 1 client.post( "/users/1/follow", headers={"Authorization": f"Bearer {token2}"}, ) # User 2 unfollows User 1 response = client.delete( "/users/1/follow", headers={"Authorization": f"Bearer {token2}"}, ) assert response.status_code == 200 assert response.json()["message"] == "Successfully unfollowed user" def test_unfollow_not_following(client: TestClient, two_users: dict): """Test unfollowing someone you don't follow.""" response = client.delete( "/users/1/follow", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) assert response.status_code == 404 assert "You are not following this user" in response.json()["detail"] def test_get_user_posts(client: TestClient, two_users: dict): """Test getting posts by a specific user.""" token1 = two_users["user1_token"] # Create two posts as User 1 for i in range(2): 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": f"User 1 post {i}"}, headers={"Authorization": f"Bearer {token1}"}, ) response = client.get("/users/1/posts") assert response.status_code == 200 posts = response.json() assert len(posts) == 2 def test_create_comment(client: TestClient, two_users: dict): """Test creating a comment.""" 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": "Comment test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # User 2 comments on the post response = client.post( f"/posts/{post_id}/comments", json={"content": "Great post!"}, headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) assert response.status_code == 201 data = response.json() assert data["content"] == "Great post!" assert data["username"] == "user2" def test_get_post_comments(client: TestClient, two_users: dict): """Test getting comments for 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": "Comments test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] # Add a comment client.post( f"/posts/{post_id}/comments", json={"content": "First comment!"}, headers={"Authorization": f"Bearer {token1}"}, ) response = client.get(f"/posts/{post_id}/comments") assert response.status_code == 200 comments = response.json() assert len(comments) == 1 assert comments[0]["content"] == "First comment!" def test_delete_comment_by_owner(client: TestClient, two_users: dict): """Test deleting own comment.""" token1 = two_users["user1_token"] # User 1 creates a post and comments 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": "Delete comment test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] comment_response = client.post( f"/posts/{post_id}/comments", json={"content": "To be deleted"}, headers={"Authorization": f"Bearer {token1}"}, ) comment_id = comment_response.json()["id"] # Delete the comment response = client.delete( f"/comments/{comment_id}", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 204 def test_delete_comment_by_non_owner(client: TestClient, two_users: dict): """Test trying to delete someone else's comment.""" token1 = two_users["user1_token"] token2 = two_users["user2_token"] # User 1 creates a post and comments 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": "Unauthorized delete test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] comment_response = client.post( f"/posts/{post_id}/comments", json={"content": "User 1's comment"}, headers={"Authorization": f"Bearer {token1}"}, ) comment_id = comment_response.json()["id"] # User 2 tries to delete it response = client.delete( f"/comments/{comment_id}", headers={"Authorization": f"Bearer {token2}"}, ) assert response.status_code == 403 assert "You can only delete your own comments" in response.json()["detail"] def test_like_comment(client: TestClient, two_users: dict): """Test liking a comment.""" token1 = two_users["user1_token"] # User 1 creates a post and comments 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": "Comment like test"}, headers={"Authorization": f"Bearer {token1}"}, ) post_id = create_response.json()["id"] comment_response = client.post( f"/posts/{post_id}/comments", json={"content": "Comment to like"}, headers={"Authorization": f"Bearer {token1}"}, ) comment_id = comment_response.json()["id"] # Like the comment response = client.post( f"/comments/{comment_id}/like", headers={"Authorization": f"Bearer {token1}"}, ) assert response.status_code == 201 assert response.json()["message"] == "Comment liked" def test_feed_global(client: TestClient, two_users: dict): """Test global feed.""" token1 = two_users["user1_token"] # User 1 creates 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": "Global feed test"}, headers={"Authorization": f"Bearer {token1}"}, ) response = client.get("/feed/global") assert response.status_code == 200 data = response.json() assert data["total"] >= 1 assert len(data["posts"]) >= 1 def test_feed_followed(client: TestClient, two_users: dict): """Test followed users feed.""" 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" client.post( "/posts", files={"image": ("test.jpg", fake_image, "image/jpeg")}, data={"caption": "Followed feed test"}, headers={"Authorization": f"Bearer {token1}"}, ) # User 2 follows User 1 client.post( "/users/1/follow", headers={"Authorization": f"Bearer {token2}"}, ) # Get followed feed for User 2 response = client.get( "/feed", headers={"Authorization": f"Bearer {token2}"}, ) assert response.status_code == 200 data = response.json() assert data["total"] >= 1 assert len(data["posts"]) >= 1 def test_feed_followed_no_follows(client: TestClient, two_users: dict): """Test followed feed when not following anyone.""" response = client.get( "/feed", headers={"Authorization": f"Bearer {two_users['user2_token']}"}, ) assert response.status_code == 200 data = response.json() assert data["total"] == 0 assert len(data["posts"]) == 0