Files
upstream-aw-server/tests/test_server.py
upstream-mirror 07fb811788
Some checks failed
Build / Test on ubuntu-latest (push) Successful in 3m6s
Lint / lint (push) Successful in 22s
Build / typecheck (ubuntu-latest, 3.9) (push) Successful in 1m49s
Lint / format (push) Successful in 42s
Build / Test on macOS-latest (push) Has been cancelled
Build / Test on windows-latest (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1m31s
snapshot of https://github.com/ActivityWatch/aw-server.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:20:00 +05:00

185 lines
5.7 KiB
Python

import random
from datetime import datetime, timedelta
import pytest
@pytest.fixture()
def bucket(flask_client):
"Context manager for creating and deleting a testing bucket"
try:
bucket_id = "test"
r = flask_client.post(
f"/api/0/buckets/{bucket_id}",
json={"client": "test", "type": "test", "hostname": "test"},
)
assert r.status_code == 200
yield bucket_id
finally:
r = flask_client.delete(f"/api/0/buckets/{bucket_id}")
assert r.status_code == 200
def test_info(flask_client):
r = flask_client.get("/api/0/info")
assert r.status_code == 200
assert r.json["testing"]
assert r.json["profile"] == "testing"
def test_buckets(flask_client, bucket, benchmark):
@benchmark
def list_buckets():
r = flask_client.get("/api/0/buckets/")
print(r.json)
assert r.status_code == 200
assert len(r.json) == 1
def test_heartbeats(flask_client, bucket, benchmark):
# FIXME: Currently tests using the memory storage method
# TODO: Test with a longer data section and see if there's a significant difference
# TODO: Test with a larger bucket and see if there's a significant difference
@benchmark
def heartbeat():
now = datetime.now()
r = flask_client.post(
f"/api/0/buckets/{bucket}/heartbeat?pulsetime=1",
json={"timestamp": now, "duration": 0, "data": {"random": random.random()}},
)
assert r.status_code == 200
def test_get_events(flask_client, bucket, benchmark):
n_events = 100
start_time = datetime.now() - timedelta(days=100)
for i in range(n_events):
now = start_time + timedelta(hours=i)
r = flask_client.post(
f"/api/0/buckets/{bucket}/heartbeat?pulsetime=0",
json={"timestamp": now, "duration": 0, "data": {"random": random.random()}},
)
assert r.status_code == 200
@benchmark
def get_events():
r = flask_client.get(f"/api/0/buckets/{bucket}/events")
assert r.status_code == 200
assert r.json
assert len(r.json) == n_events
r = flask_client.get(f"/api/0/buckets/{bucket}/events?limit=-1")
assert r.status_code == 200
assert r.json
assert len(r.json) == n_events
r = flask_client.get(f"/api/0/buckets/{bucket}/events?limit=10")
assert r.status_code == 200
assert r.json
assert len(r.json) == 10
r = flask_client.get(f"/api/0/buckets/{bucket}/events?limit=100")
assert r.status_code == 200
assert r.json
assert len(r.json) == n_events
r = flask_client.get(f"/api/0/buckets/{bucket}/events?limit=1000")
assert r.status_code == 200
assert r.json
assert len(r.json) == n_events
def test_insert_event_returns_list(flask_client, bucket):
"""Test that POST /events returns a list of events with IDs (matching aw-server-rust)."""
now = datetime.now()
event_data = {
"timestamp": now.isoformat(),
"duration": 0,
"data": {"label": "test"},
}
# Single event as list
r = flask_client.post(
f"/api/0/buckets/{bucket}/events",
json=[event_data],
)
assert r.status_code == 200
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
assert len(r.json) == 1
assert r.json[0]["id"] is not None
assert r.json[0]["data"] == {"label": "test"}
# Single event as dict (legacy format)
r = flask_client.post(
f"/api/0/buckets/{bucket}/events",
json=event_data,
)
assert r.status_code == 200
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
assert len(r.json) == 1
assert r.json[0]["id"] is not None
def test_insert_events_returns_list(flask_client, bucket):
"""Test that POST /events with multiple events returns a list."""
now = datetime.now()
events_data = [
{
"timestamp": (now - timedelta(hours=i)).isoformat(),
"duration": 0,
"data": {"label": f"test-{i}"},
}
for i in range(3)
]
r = flask_client.post(
f"/api/0/buckets/{bucket}/events",
json=events_data,
)
assert r.status_code == 200
assert isinstance(r.json, list), f"Expected list, got {type(r.json)}"
assert len(r.json) == 0
# TODO: Add benchmark for basic AFK-filtering query
def test_query_invalid_timeperiod(flask_client):
"""Malformed timeperiods must yield 400 (client error), not 500.
Regression test: a non-ISO8601 timeperiod previously raised an uncaught
iso8601.ParseError, surfacing as an Internal Server Error.
"""
r = flask_client.post(
"/api/0/query/",
json={"query": ["RETURN = 1;"], "timeperiods": ["not-a-valid-period"]},
)
assert r.status_code == 400
assert "not-a-valid-period" in r.json["message"]
def test_query_timeperiod_missing_slash(flask_client):
"""A timeperiod without a start/end slash separator must yield 400, not 500.
Regression test: a single ISO8601 datetime (no slash) previously raised an
uncaught IndexError when indexing the split result.
"""
r = flask_client.post(
"/api/0/query/",
json={"query": ["RETURN = 1;"], "timeperiods": ["2024-01-01T00:00:00+00:00"]},
)
assert r.status_code == 400
def test_query_valid_timeperiod(flask_client):
"""A well-formed query with a valid timeperiod still succeeds."""
r = flask_client.post(
"/api/0/query/",
json={
"query": ["RETURN = 1;"],
"timeperiods": ["2024-01-01T00:00:00+00:00/2024-01-02T00:00:00+00:00"],
},
)
assert r.status_code == 200
assert r.json == [1]