Files
instagram-clone/tests/test_posts.py
OpenClaw Agent a3eca3b7da feat: implement Instagram clone SocialPhoto API
- FastAPI backend with SQLite database
- JWT authentication (register, login)
- User profiles with follow/unfollow
- Posts with image upload and likes/dislikes
- Comments with likes
- Global and personalized feed
- Comprehensive pytest test suite (37 tests)

TASK-ID: 758f4029-702
2026-04-16 03:20:48 +00:00

293 lines
8.8 KiB
Python

"""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