test_dashboard_api.py
4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""Test /api/dashboard endpoint"""
import pytest
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from app import app as flask_app
@pytest.fixture
def client():
flask_app.config['TESTING'] = True
with flask_app.test_client() as c:
yield c
def test_dashboard_returns_200(client):
"""Dashboard API returns HTTP 200"""
r = client.get('/api/dashboard')
assert r.status_code == 200
def test_dashboard_returns_json(client):
"""Dashboard API returns valid JSON"""
r = client.get('/api/dashboard')
data = r.get_json()
assert data is not None
assert data.get('ok') is True
def test_dashboard_has_all_modules(client):
"""Dashboard response includes all metric modules"""
r = client.get('/api/dashboard')
data = r.get_json()['data']
required_modules = ['chats', 'articles', 'learn', 'reports', 'jobs',
'auto_reply', 'circle']
for module in required_modules:
assert module in data, f"Missing module: {module}"
def test_chats_module(client):
"""Chats module has expected fields"""
r = client.get('/api/dashboard')
chats = r.get_json()['data']['chats']
fields = ['groups', 'messages', 'speakers', 'shares']
for f in fields:
assert f in chats, f"Missing chats.{f}"
def test_articles_module(client):
"""Articles module has expected fields"""
r = client.get('/api/dashboard')
articles = r.get_json()['data']['articles']
fields = ['total', 'summarized', 'unsummarized', 'learned', 'unlearned']
for f in fields:
assert f in articles, f"Missing articles.{f}"
def test_learn_module(client):
"""Learn module has expected fields"""
r = client.get('/api/dashboard')
learn = r.get_json()['data']['learn']
fields = ['pending_review', 'approved', 'applied', 'rejected', 'unclassified']
for f in fields:
assert f in learn, f"Missing learn.{f}"
assert 'by_type' in learn
for t in ['skill', 'memory', 'todo', 'reference']:
assert t in learn['by_type'], f"Missing learn.by_type.{t}"
def test_reports_module(client):
"""Reports module has expected fields"""
r = client.get('/api/dashboard')
reports = r.get_json()['data']['reports']
fields = ['daily', 'summaries', 'learn_records', 'images']
for f in fields:
assert f in reports, f"Missing reports.{f}"
assert 'last_generated' in reports
def test_jobs_module(client):
"""Jobs module has expected fields"""
r = client.get('/api/dashboard')
jobs = r.get_json()['data']['jobs']
fields = ['total', 'running', 'completed', 'failed', 'success_rate']
for f in fields:
assert f in jobs, f"Missing jobs.{f}"
assert 'last_completed' in jobs
def test_auto_reply_module(client):
"""Auto reply module has expected fields"""
r = client.get('/api/dashboard')
ar = r.get_json()['data']['auto_reply']
fields = ['whitelist', 'pending', 'sent']
for f in fields:
assert f in ar, f"Missing auto_reply.{f}"
def test_circle_module(client):
"""Circle module has expected fields"""
r = client.get('/api/dashboard')
circle = r.get_json()['data']['circle']
fields = ['conversations', 'messages']
for f in fields:
assert f in circle, f"Missing circle.{f}"
def test_values_are_integers(client):
"""All count values are integers (or null for WeChat DB failures)"""
r = client.get('/api/dashboard')
data = r.get_json()['data']
def check_int(val, path):
if val is None:
return # WeChat DB may be unavailable
assert isinstance(val, (int, float)), f"{path} should be int/float, got {type(val)}: {val}"
check_int(data['articles']['total'], 'articles.total')
check_int(data['learn']['pending_review'], 'learn.pending_review')
check_int(data['jobs']['total'], 'jobs.total')
check_int(data['reports']['daily'], 'reports.daily')
check_int(data['auto_reply']['whitelist'], 'auto_reply.whitelist')
check_int(data['circle']['conversations'], 'circle.conversations')
if __name__ == '__main__':
pytest.main([__file__, '-v'])