170 lines
6.3 KiB
Python
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."
|