SurfSmart/test/tests_backend/test_activity.py
2025-06-09 17:53:19 +08:00

170 lines
6.3 KiB
Python

import json
import pytest
from backend.app import create_app
@pytest.fixture
def client():
"""
Creates a test client from your Flask app.
"""
app = create_app()
app.config["TESTING"] = True
with app.test_client() as client:
yield client
@pytest.fixture
def auth_headers(client):
"""
Registers a test user and returns an authorization header.
"""
import uuid
unique_suffix = str(uuid.uuid4())[:8]
username = f"activityuser_{unique_suffix}"
email = f"{username}@example.com"
reg_payload = {"username": username, "email": email, "password": "TestPassword123"}
reg_resp = client.post("/api/register", data=json.dumps(reg_payload), content_type="application/json")
assert reg_resp.status_code == 201, f"Registration failed: {reg_resp.data.decode()}"
data = json.loads(reg_resp.data)
token = data["token"]
return {"Authorization": f"Bearer {token}"}
@pytest.fixture
def project_id(client, auth_headers):
"""
Creates a project for the user so we can attach activity logs to it.
Returns the project ID as a string.
"""
payload = {
"name": "Activity Test Project",
"topic": "Log Testing",
"description": "Project used for testing activity logs."
}
resp = client.post("/api/projects", data=json.dumps(payload),
content_type="application/json", headers=auth_headers)
assert resp.status_code == 201, f"Project creation failed: {resp.data.decode()}"
data = json.loads(resp.data)
return data["project_id"]
def test_list_activity_empty(client, auth_headers, project_id):
"""
No logs exist initially, so listing with ?projectId=xxx returns empty array.
"""
url = f"/api/project_activity?projectId={project_id}"
resp = client.get(url, headers=auth_headers)
assert resp.status_code == 200, f"List logs failed: {resp.data.decode()}"
data = json.loads(resp.data)
assert "activity_logs" in data
assert len(data["activity_logs"]) == 0
def test_create_activity(client, auth_headers, project_id):
"""
Create an activity log for the project, then verify it appears in the listing.
"""
payload = {
"projectId": project_id,
"activityType": "URL added",
"message": "Added a new URL to the project."
}
create_resp = client.post("/api/project_activity",
data=json.dumps(payload),
content_type="application/json",
headers=auth_headers)
assert create_resp.status_code == 201, f"Create activity failed: {create_resp.data.decode()}"
create_data = json.loads(create_resp.data)
assert "activity_id" in create_data
# Now list logs
list_resp = client.get(f"/api/project_activity?projectId={project_id}", headers=auth_headers)
assert list_resp.status_code == 200
list_data = json.loads(list_resp.data)
logs = list_data.get("activity_logs", [])
assert len(logs) == 1
assert logs[0]["activityType"] == "URL added"
assert logs[0]["message"] == "Added a new URL to the project."
def test_create_activity_invalid_project(client, auth_headers):
"""
If projectId is invalid or not found, we expect 400 or 404.
"""
# Invalid format
payload1 = {
"projectId": "not_a_valid_objectid",
"activityType": "Test",
"message": ""
}
resp1 = client.post("/api/project_activity",
data=json.dumps(payload1),
content_type="application/json",
headers=auth_headers)
assert resp1.status_code == 400, f"Expected 400 for invalid projectId format, got {resp1.status_code}"
# 404 if project doesn't exist
payload2 = {
"projectId": "64f3f000000000000000abcd", # random objectId
"activityType": "Test",
"message": ""
}
resp2 = client.post("/api/project_activity",
data=json.dumps(payload2),
content_type="application/json",
headers=auth_headers)
assert resp2.status_code == 404, f"Expected 404 for non-existent project, got {resp2.status_code}"
def test_list_activity_pagination(client, auth_headers, project_id):
"""
Create multiple logs, then retrieve them with offset/limit.
"""
# Create 5 logs
for i in range(5):
pay = {
"projectId": project_id,
"activityType": f"LogType{i}",
"message": f"Message {i}"
}
resp = client.post("/api/project_activity",
data=json.dumps(pay),
content_type="application/json",
headers=auth_headers)
assert resp.status_code == 201
# List with limit=2, offset=0
resp_list1 = client.get(f"/api/project_activity?projectId={project_id}&limit=2&offset=0", headers=auth_headers)
assert resp_list1.status_code == 200
data1 = json.loads(resp_list1.data)
logs1 = data1["activity_logs"]
assert len(logs1) == 2
# List with limit=2, offset=2
resp_list2 = client.get(f"/api/project_activity?projectId={project_id}&limit=2&offset=2", headers=auth_headers)
data2 = json.loads(resp_list2.data)
logs2 = data2["activity_logs"]
assert len(logs2) == 2
def test_delete_activity(client, auth_headers, project_id):
"""
By default, only the project owner can delete logs. We'll test that scenario.
"""
# Create a log
payload = {
"projectId": project_id,
"activityType": "DeleteCheck",
"message": "Testing delete."
}
create_resp = client.post("/api/project_activity",
data=json.dumps(payload),
content_type="application/json",
headers=auth_headers)
assert create_resp.status_code == 201
activity_id = json.loads(create_resp.data)["activity_id"]
# Delete it
del_resp = client.delete(f"/api/project_activity/{activity_id}", headers=auth_headers)
assert del_resp.status_code == 200, f"Delete log failed: {del_resp.data.decode()}"
# Confirm it's gone
list_resp = client.get(f"/api/project_activity?projectId={project_id}", headers=auth_headers)
data = json.loads(list_resp.data)
logs_left = [a for a in data["activity_logs"] if a["_id"] == activity_id]
assert len(logs_left) == 0, "Activity log was not deleted properly."