argus-alm 0.15.2__py3-none-any.whl → 0.15.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- argus/_version.py +2 -2
- argus/client/base.py +14 -8
- argus/client/generic/cli.py +3 -2
- argus/client/generic/client.py +2 -1
- argus/client/generic_result.py +6 -1
- argus/client/sct/client.py +2 -1
- argus/common/enums.py +16 -0
- {argus_alm-0.15.2.dist-info → argus_alm-0.15.5.dist-info}/METADATA +4 -4
- argus_alm-0.15.5.dist-info/RECORD +22 -0
- argus/backend/.gitkeep +0 -0
- argus/backend/__init__.py +0 -0
- argus/backend/cli.py +0 -57
- argus/backend/controller/__init__.py +0 -0
- argus/backend/controller/admin.py +0 -20
- argus/backend/controller/admin_api.py +0 -355
- argus/backend/controller/api.py +0 -589
- argus/backend/controller/auth.py +0 -67
- argus/backend/controller/client_api.py +0 -109
- argus/backend/controller/main.py +0 -316
- argus/backend/controller/notification_api.py +0 -72
- argus/backend/controller/notifications.py +0 -13
- argus/backend/controller/planner_api.py +0 -194
- argus/backend/controller/team.py +0 -129
- argus/backend/controller/team_ui.py +0 -19
- argus/backend/controller/testrun_api.py +0 -513
- argus/backend/controller/view_api.py +0 -188
- argus/backend/controller/views_widgets/__init__.py +0 -0
- argus/backend/controller/views_widgets/graphed_stats.py +0 -54
- argus/backend/controller/views_widgets/graphs.py +0 -68
- argus/backend/controller/views_widgets/highlights.py +0 -135
- argus/backend/controller/views_widgets/nemesis_stats.py +0 -26
- argus/backend/controller/views_widgets/summary.py +0 -43
- argus/backend/db.py +0 -98
- argus/backend/error_handlers.py +0 -41
- argus/backend/events/event_processors.py +0 -34
- argus/backend/models/__init__.py +0 -0
- argus/backend/models/argus_ai.py +0 -24
- argus/backend/models/github_issue.py +0 -60
- argus/backend/models/plan.py +0 -24
- argus/backend/models/result.py +0 -187
- argus/backend/models/runtime_store.py +0 -58
- argus/backend/models/view_widgets.py +0 -25
- argus/backend/models/web.py +0 -403
- argus/backend/plugins/__init__.py +0 -0
- argus/backend/plugins/core.py +0 -248
- argus/backend/plugins/driver_matrix_tests/controller.py +0 -66
- argus/backend/plugins/driver_matrix_tests/model.py +0 -429
- argus/backend/plugins/driver_matrix_tests/plugin.py +0 -21
- argus/backend/plugins/driver_matrix_tests/raw_types.py +0 -62
- argus/backend/plugins/driver_matrix_tests/service.py +0 -61
- argus/backend/plugins/driver_matrix_tests/udt.py +0 -42
- argus/backend/plugins/generic/model.py +0 -86
- argus/backend/plugins/generic/plugin.py +0 -15
- argus/backend/plugins/generic/types.py +0 -14
- argus/backend/plugins/loader.py +0 -39
- argus/backend/plugins/sct/controller.py +0 -224
- argus/backend/plugins/sct/plugin.py +0 -37
- argus/backend/plugins/sct/resource_setup.py +0 -177
- argus/backend/plugins/sct/service.py +0 -682
- argus/backend/plugins/sct/testrun.py +0 -288
- argus/backend/plugins/sct/udt.py +0 -100
- argus/backend/plugins/sirenada/model.py +0 -118
- argus/backend/plugins/sirenada/plugin.py +0 -16
- argus/backend/service/admin.py +0 -26
- argus/backend/service/argus_service.py +0 -696
- argus/backend/service/build_system_monitor.py +0 -185
- argus/backend/service/client_service.py +0 -127
- argus/backend/service/event_service.py +0 -18
- argus/backend/service/github_service.py +0 -233
- argus/backend/service/jenkins_service.py +0 -269
- argus/backend/service/notification_manager.py +0 -159
- argus/backend/service/planner_service.py +0 -608
- argus/backend/service/release_manager.py +0 -229
- argus/backend/service/results_service.py +0 -690
- argus/backend/service/stats.py +0 -610
- argus/backend/service/team_manager_service.py +0 -82
- argus/backend/service/test_lookup.py +0 -172
- argus/backend/service/testrun.py +0 -489
- argus/backend/service/user.py +0 -308
- argus/backend/service/views.py +0 -219
- argus/backend/service/views_widgets/__init__.py +0 -0
- argus/backend/service/views_widgets/graphed_stats.py +0 -180
- argus/backend/service/views_widgets/highlights.py +0 -374
- argus/backend/service/views_widgets/nemesis_stats.py +0 -34
- argus/backend/template_filters.py +0 -27
- argus/backend/tests/__init__.py +0 -0
- argus/backend/tests/client_service/__init__.py +0 -0
- argus/backend/tests/client_service/test_submit_results.py +0 -79
- argus/backend/tests/conftest.py +0 -180
- argus/backend/tests/results_service/__init__.py +0 -0
- argus/backend/tests/results_service/test_best_results.py +0 -178
- argus/backend/tests/results_service/test_cell.py +0 -65
- argus/backend/tests/results_service/test_chartjs_additional_functions.py +0 -259
- argus/backend/tests/results_service/test_create_chartjs.py +0 -220
- argus/backend/tests/results_service/test_result_metadata.py +0 -100
- argus/backend/tests/results_service/test_results_service.py +0 -203
- argus/backend/tests/results_service/test_validation_rules.py +0 -213
- argus/backend/tests/view_widgets/__init__.py +0 -0
- argus/backend/tests/view_widgets/test_highlights_api.py +0 -532
- argus/backend/util/common.py +0 -65
- argus/backend/util/config.py +0 -38
- argus/backend/util/encoders.py +0 -56
- argus/backend/util/logsetup.py +0 -80
- argus/backend/util/module_loaders.py +0 -30
- argus/backend/util/send_email.py +0 -91
- argus/client/tests/__init__.py +0 -0
- argus/client/tests/conftest.py +0 -19
- argus/client/tests/test_package.py +0 -45
- argus/client/tests/test_results.py +0 -224
- argus_alm-0.15.2.dist-info/RECORD +0 -122
- {argus_alm-0.15.2.dist-info → argus_alm-0.15.5.dist-info}/WHEEL +0 -0
- {argus_alm-0.15.2.dist-info → argus_alm-0.15.5.dist-info}/entry_points.txt +0 -0
- {argus_alm-0.15.2.dist-info → argus_alm-0.15.5.dist-info}/licenses/LICENSE +0 -0
- {argus_alm-0.15.2.dist-info → argus_alm-0.15.5.dist-info}/top_level.txt +0 -0
|
@@ -1,532 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import time
|
|
3
|
-
from datetime import datetime, UTC
|
|
4
|
-
from unittest.mock import patch
|
|
5
|
-
from uuid import uuid4, UUID
|
|
6
|
-
|
|
7
|
-
from flask import g
|
|
8
|
-
|
|
9
|
-
from argus.backend.models.view_widgets import WidgetHighlights, WidgetComment
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@patch("argus.backend.service.views_widgets.highlights.HighlightsService._send_highlight_notifications")
|
|
13
|
-
def test_create_highlight_should_return_created_highlight(notifications, flask_client):
|
|
14
|
-
view_id = str(uuid4())
|
|
15
|
-
now = datetime.now(UTC)
|
|
16
|
-
response = flask_client.post(
|
|
17
|
-
"/api/v1/views/widgets/highlights/create",
|
|
18
|
-
data=json.dumps({"view_id": view_id, "index": 0, "content": "Highlight content", "is_task": False}),
|
|
19
|
-
content_type="application/json",
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
assert response.status_code == 200, response.text
|
|
23
|
-
assert response.json["status"] == "ok"
|
|
24
|
-
assert response.json["response"]["view_id"] == view_id
|
|
25
|
-
assert response.json["response"]["content"] == "Highlight content"
|
|
26
|
-
assert response.json["response"]["archived_at"] == 0
|
|
27
|
-
assert response.json["response"]["comments_count"] == 0
|
|
28
|
-
assert response.json["response"]["creator_id"] == str(g.user.id)
|
|
29
|
-
assert response.json["response"]["created_at"] > now.timestamp()
|
|
30
|
-
assert "completed" not in response.json["response"]
|
|
31
|
-
assert "assignee_id" not in response.json["response"]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@patch("argus.backend.service.views_widgets.highlights.HighlightsService._send_highlight_notifications")
|
|
35
|
-
def test_create_action_item_should_return_created_action_item(notifications, flask_client):
|
|
36
|
-
view_id = str(uuid4())
|
|
37
|
-
now = datetime.now(UTC)
|
|
38
|
-
response = flask_client.post(
|
|
39
|
-
"/api/v1/views/widgets/highlights/create",
|
|
40
|
-
data=json.dumps({"view_id": view_id, "index": 0, "content": "Action item content", "is_task": True}),
|
|
41
|
-
content_type="application/json",
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
assert response.status_code == 200, response.text
|
|
45
|
-
assert response.json["status"] == "ok"
|
|
46
|
-
assert response.json["response"]["view_id"] == view_id
|
|
47
|
-
assert response.json["response"]["content"] == "Action item content"
|
|
48
|
-
assert response.json["response"]["completed"] is False
|
|
49
|
-
assert response.json["response"]["assignee_id"] is None
|
|
50
|
-
assert response.json["response"]["archived_at"] == 0
|
|
51
|
-
assert response.json["response"]["comments_count"] == 0
|
|
52
|
-
assert response.json["response"]["creator_id"] == str(g.user.id)
|
|
53
|
-
assert response.json["response"]["created_at"] > now.timestamp()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_get_highlights_should_return_highlights_and_action_items(flask_client):
|
|
57
|
-
view_id = str(uuid4())
|
|
58
|
-
creator_id = g.user.id
|
|
59
|
-
|
|
60
|
-
highlight_entry = WidgetHighlights(
|
|
61
|
-
view_id=UUID(view_id),
|
|
62
|
-
index=0,
|
|
63
|
-
created_at=datetime.now(UTC),
|
|
64
|
-
creator_id=creator_id,
|
|
65
|
-
content="Test highlight",
|
|
66
|
-
completed=None,
|
|
67
|
-
comments_count=0,
|
|
68
|
-
)
|
|
69
|
-
highlight_entry.save()
|
|
70
|
-
|
|
71
|
-
action_item_entry = WidgetHighlights(
|
|
72
|
-
view_id=UUID(view_id),
|
|
73
|
-
index=0,
|
|
74
|
-
created_at=datetime.now(UTC),
|
|
75
|
-
creator_id=creator_id,
|
|
76
|
-
content="Test action item",
|
|
77
|
-
completed=False,
|
|
78
|
-
comments_count=0,
|
|
79
|
-
)
|
|
80
|
-
action_item_entry.save()
|
|
81
|
-
|
|
82
|
-
# Add small delay to ensure can be read (test was flaky)
|
|
83
|
-
time.sleep(0.05) # 50ms delay
|
|
84
|
-
|
|
85
|
-
response = flask_client.get(f"/api/v1/views/widgets/highlights?view_id={view_id}&index=0")
|
|
86
|
-
|
|
87
|
-
assert response.status_code == 200
|
|
88
|
-
assert response.json["status"] == "ok"
|
|
89
|
-
highlights = response.json["response"]["highlights"]
|
|
90
|
-
action_items = response.json["response"]["action_items"]
|
|
91
|
-
|
|
92
|
-
assert len(highlights) == 1
|
|
93
|
-
assert len(action_items) == 1
|
|
94
|
-
assert highlights[0]["content"] == "Test highlight"
|
|
95
|
-
assert action_items[0]["content"] == "Test action item"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def test_archive_highlight_should_mark_highlight_as_archived(flask_client):
|
|
99
|
-
view_id = str(uuid4())
|
|
100
|
-
created_at = datetime.now(UTC)
|
|
101
|
-
creator_id = g.user.id
|
|
102
|
-
highlight_entry = WidgetHighlights(
|
|
103
|
-
view_id=UUID(view_id),
|
|
104
|
-
index=0,
|
|
105
|
-
created_at=created_at,
|
|
106
|
-
creator_id=creator_id,
|
|
107
|
-
content="Test highlight",
|
|
108
|
-
completed=None,
|
|
109
|
-
comments_count=0,
|
|
110
|
-
archived_at=datetime.fromtimestamp(0, tz=UTC),
|
|
111
|
-
)
|
|
112
|
-
highlight_entry.save()
|
|
113
|
-
|
|
114
|
-
response = flask_client.post(
|
|
115
|
-
"/api/v1/views/widgets/highlights/archive",
|
|
116
|
-
data=json.dumps(
|
|
117
|
-
{
|
|
118
|
-
"view_id": view_id,
|
|
119
|
-
"index": 0,
|
|
120
|
-
"created_at": created_at.timestamp(),
|
|
121
|
-
}
|
|
122
|
-
),
|
|
123
|
-
content_type="application/json",
|
|
124
|
-
)
|
|
125
|
-
assert response.status_code == 200
|
|
126
|
-
assert response.json["status"] == "ok"
|
|
127
|
-
|
|
128
|
-
archived_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
|
|
129
|
-
assert archived_entry.archived_at.replace(tzinfo=UTC) > created_at
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def test_unarchive_highlight_should_unmark_highlight_from_archived(flask_client):
|
|
133
|
-
view_id = str(uuid4())
|
|
134
|
-
created_at = datetime.now(UTC)
|
|
135
|
-
creator_id = g.user.id
|
|
136
|
-
archived_time = datetime.now(UTC)
|
|
137
|
-
highlight_entry = WidgetHighlights(
|
|
138
|
-
view_id=UUID(view_id),
|
|
139
|
-
index=0,
|
|
140
|
-
created_at=created_at,
|
|
141
|
-
creator_id=creator_id,
|
|
142
|
-
content="Test highlight",
|
|
143
|
-
completed=None,
|
|
144
|
-
comments_count=0,
|
|
145
|
-
archived_at=archived_time,
|
|
146
|
-
)
|
|
147
|
-
highlight_entry.save()
|
|
148
|
-
|
|
149
|
-
response = flask_client.post(
|
|
150
|
-
"/api/v1/views/widgets/highlights/unarchive",
|
|
151
|
-
data=json.dumps(
|
|
152
|
-
{
|
|
153
|
-
"view_id": view_id,
|
|
154
|
-
"index": 0,
|
|
155
|
-
"created_at": created_at.timestamp(),
|
|
156
|
-
}
|
|
157
|
-
),
|
|
158
|
-
content_type="application/json",
|
|
159
|
-
)
|
|
160
|
-
assert response.status_code == 200
|
|
161
|
-
assert response.json["status"] == "ok"
|
|
162
|
-
|
|
163
|
-
unarchived_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
|
|
164
|
-
assert unarchived_entry.archived_at.replace(tzinfo=UTC) == datetime.fromtimestamp(0, tz=UTC)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
@patch("argus.backend.service.views_widgets.highlights.HighlightsService._send_highlight_notifications")
|
|
168
|
-
def test_update_highlight_should_update_content_for_creator(notifications, flask_client):
|
|
169
|
-
view_id = str(uuid4())
|
|
170
|
-
created_at = datetime.now(UTC)
|
|
171
|
-
creator_id = g.user.id
|
|
172
|
-
original_content = "Original content"
|
|
173
|
-
updated_content = "Updated content"
|
|
174
|
-
|
|
175
|
-
highlight_entry = WidgetHighlights(
|
|
176
|
-
view_id=UUID(view_id),
|
|
177
|
-
index=0,
|
|
178
|
-
created_at=created_at,
|
|
179
|
-
creator_id=creator_id,
|
|
180
|
-
content=original_content,
|
|
181
|
-
completed=None,
|
|
182
|
-
comments_count=0,
|
|
183
|
-
archived_at=datetime.fromtimestamp(0, tz=UTC),
|
|
184
|
-
)
|
|
185
|
-
highlight_entry.save()
|
|
186
|
-
|
|
187
|
-
response = flask_client.post(
|
|
188
|
-
"/api/v1/views/widgets/highlights/update",
|
|
189
|
-
data=json.dumps({
|
|
190
|
-
"view_id": view_id,
|
|
191
|
-
"index": 0,
|
|
192
|
-
"created_at": created_at.timestamp(),
|
|
193
|
-
"content": updated_content,
|
|
194
|
-
}),
|
|
195
|
-
content_type="application/json",
|
|
196
|
-
)
|
|
197
|
-
assert response.status_code == 200
|
|
198
|
-
assert response.json["status"] == "ok"
|
|
199
|
-
assert response.json["response"]["content"] == updated_content
|
|
200
|
-
|
|
201
|
-
updated_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
|
|
202
|
-
assert updated_entry.content == updated_content
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
def test_update_highlight_should_forbid_non_creator(flask_client):
|
|
206
|
-
view_id = str(uuid4())
|
|
207
|
-
created_at = datetime.now(UTC)
|
|
208
|
-
creator_id = uuid4() # Different from the logged-in user
|
|
209
|
-
original_content = "Original content"
|
|
210
|
-
malicious_content = "Malicious update"
|
|
211
|
-
|
|
212
|
-
highlight_entry = WidgetHighlights(
|
|
213
|
-
view_id=UUID(view_id),
|
|
214
|
-
index=0,
|
|
215
|
-
created_at=created_at,
|
|
216
|
-
creator_id=creator_id,
|
|
217
|
-
content=original_content,
|
|
218
|
-
completed=None,
|
|
219
|
-
comments_count=0,
|
|
220
|
-
archived_at=datetime.fromtimestamp(0, tz=UTC),
|
|
221
|
-
)
|
|
222
|
-
highlight_entry.save()
|
|
223
|
-
|
|
224
|
-
response = flask_client.post(
|
|
225
|
-
"/api/v1/views/widgets/highlights/update",
|
|
226
|
-
data=json.dumps({
|
|
227
|
-
"view_id": view_id,
|
|
228
|
-
"index": 0,
|
|
229
|
-
"created_at": created_at.timestamp(),
|
|
230
|
-
"content": malicious_content,
|
|
231
|
-
}),
|
|
232
|
-
content_type="application/json",
|
|
233
|
-
)
|
|
234
|
-
assert response.status_code == 200, response.text
|
|
235
|
-
assert response.json["status"] == "error"
|
|
236
|
-
assert response.json["response"]["exception"] == "Forbidden"
|
|
237
|
-
|
|
238
|
-
unchanged_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
|
|
239
|
-
assert unchanged_entry.content == original_content
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
def test_set_completed_should_update_completed_status(flask_client):
|
|
243
|
-
view_id = str(uuid4())
|
|
244
|
-
created_at = datetime.now(UTC)
|
|
245
|
-
action_item_entry = WidgetHighlights(
|
|
246
|
-
view_id=UUID(view_id),
|
|
247
|
-
index=0,
|
|
248
|
-
created_at=created_at,
|
|
249
|
-
creator_id=g.user.id,
|
|
250
|
-
content="Test action item",
|
|
251
|
-
completed=False,
|
|
252
|
-
comments_count=0,
|
|
253
|
-
)
|
|
254
|
-
action_item_entry.save()
|
|
255
|
-
|
|
256
|
-
# Set completed to True
|
|
257
|
-
response = flask_client.post(
|
|
258
|
-
"/api/v1/views/widgets/highlights/set_completed",
|
|
259
|
-
data=json.dumps({
|
|
260
|
-
"view_id": view_id,
|
|
261
|
-
"index": 0,
|
|
262
|
-
"created_at": created_at.timestamp(),
|
|
263
|
-
"completed": True
|
|
264
|
-
}),
|
|
265
|
-
content_type="application/json",
|
|
266
|
-
)
|
|
267
|
-
assert response.status_code == 200
|
|
268
|
-
assert response.json["status"] == "ok"
|
|
269
|
-
assert response.json["response"]["completed"] is True
|
|
270
|
-
|
|
271
|
-
# Set completed to False
|
|
272
|
-
response = flask_client.post(
|
|
273
|
-
"/api/v1/views/widgets/highlights/set_completed",
|
|
274
|
-
data=json.dumps({
|
|
275
|
-
"view_id": view_id,
|
|
276
|
-
"index": 0,
|
|
277
|
-
"created_at": created_at.timestamp(),
|
|
278
|
-
"completed": False
|
|
279
|
-
}),
|
|
280
|
-
content_type="application/json",
|
|
281
|
-
)
|
|
282
|
-
assert response.status_code == 200
|
|
283
|
-
assert response.json["response"]["completed"] is False
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
def test_set_completed_should_not_work_for_highlight(flask_client):
|
|
287
|
-
view_id = str(uuid4())
|
|
288
|
-
created_at = datetime.now(UTC)
|
|
289
|
-
highlight_entry = WidgetHighlights(
|
|
290
|
-
view_id=UUID(view_id),
|
|
291
|
-
index=0,
|
|
292
|
-
created_at=created_at,
|
|
293
|
-
creator_id=g.user.id,
|
|
294
|
-
content="Test highlight",
|
|
295
|
-
completed=None,
|
|
296
|
-
comments_count=0,
|
|
297
|
-
)
|
|
298
|
-
highlight_entry.save()
|
|
299
|
-
|
|
300
|
-
response = flask_client.post(
|
|
301
|
-
"/api/v1/views/widgets/highlights/set_completed",
|
|
302
|
-
data=json.dumps({
|
|
303
|
-
"view_id": view_id,
|
|
304
|
-
"index": 0,
|
|
305
|
-
"created_at": created_at.timestamp(),
|
|
306
|
-
"completed": True
|
|
307
|
-
}),
|
|
308
|
-
content_type="application/json",
|
|
309
|
-
)
|
|
310
|
-
assert response.status_code == 200, response.text
|
|
311
|
-
assert response.json["status"] == "error"
|
|
312
|
-
assert response.json["response"]["exception"] == "NotFound"
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
@patch("argus.backend.controller.views_widgets.highlights.HighlightsService.send_action_notification")
|
|
316
|
-
def test_set_assignee_should_set_assignee_for_action_item(notification, flask_client):
|
|
317
|
-
view_id = str(uuid4())
|
|
318
|
-
created_at = datetime.now(UTC)
|
|
319
|
-
action_item_entry = WidgetHighlights(
|
|
320
|
-
view_id=UUID(view_id),
|
|
321
|
-
index=0,
|
|
322
|
-
created_at=created_at,
|
|
323
|
-
creator_id=g.user.id,
|
|
324
|
-
content="Test action item",
|
|
325
|
-
completed=False,
|
|
326
|
-
comments_count=0,
|
|
327
|
-
)
|
|
328
|
-
action_item_entry.save()
|
|
329
|
-
|
|
330
|
-
new_assignee_id = str(uuid4())
|
|
331
|
-
|
|
332
|
-
response = flask_client.post(
|
|
333
|
-
"/api/v1/views/widgets/highlights/set_assignee",
|
|
334
|
-
data=json.dumps({
|
|
335
|
-
"view_id": view_id,
|
|
336
|
-
"index": 0,
|
|
337
|
-
"created_at": created_at.timestamp(),
|
|
338
|
-
"assignee_id": new_assignee_id
|
|
339
|
-
}),
|
|
340
|
-
content_type="application/json",
|
|
341
|
-
)
|
|
342
|
-
assert response.status_code == 200
|
|
343
|
-
assert response.json["status"] == "ok"
|
|
344
|
-
assert response.json["response"]["assignee_id"] == new_assignee_id
|
|
345
|
-
assert notification.call_count == 1
|
|
346
|
-
|
|
347
|
-
updated_entry = WidgetHighlights.objects(view_id=UUID(view_id), index=0, created_at=created_at).first()
|
|
348
|
-
assert str(updated_entry.assignee_id) == new_assignee_id
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
def test_set_assignee_should_not_work_for_highlight(flask_client):
|
|
352
|
-
view_id = str(uuid4())
|
|
353
|
-
created_at = datetime.now(UTC)
|
|
354
|
-
highlight_entry = WidgetHighlights(
|
|
355
|
-
view_id=UUID(view_id),
|
|
356
|
-
index=0,
|
|
357
|
-
created_at=created_at,
|
|
358
|
-
creator_id=g.user.id,
|
|
359
|
-
content="Test highlight",
|
|
360
|
-
completed=None,
|
|
361
|
-
comments_count=0,
|
|
362
|
-
)
|
|
363
|
-
highlight_entry.save()
|
|
364
|
-
|
|
365
|
-
new_assignee_id = str(uuid4())
|
|
366
|
-
|
|
367
|
-
response = flask_client.post(
|
|
368
|
-
"/api/v1/views/widgets/highlights/set_assignee",
|
|
369
|
-
data=json.dumps({
|
|
370
|
-
"view_id": view_id,
|
|
371
|
-
"index": 0,
|
|
372
|
-
"created_at": created_at.timestamp(),
|
|
373
|
-
"assignee_id": new_assignee_id
|
|
374
|
-
}),
|
|
375
|
-
content_type="application/json",
|
|
376
|
-
)
|
|
377
|
-
assert response.status_code == 200, response.text
|
|
378
|
-
assert response.json["status"] == "error"
|
|
379
|
-
assert response.json["response"]["exception"] == "NotFound"
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
@patch("argus.backend.service.views_widgets.highlights.HighlightsService._send_highlight_notifications")
|
|
383
|
-
def test_create_comment_should_increment_comments_count(notification, flask_client):
|
|
384
|
-
view_id = str(uuid4())
|
|
385
|
-
highlight_created_at = datetime.now(UTC)
|
|
386
|
-
highlight_entry = WidgetHighlights(
|
|
387
|
-
view_id=UUID(view_id),
|
|
388
|
-
index=0,
|
|
389
|
-
created_at=highlight_created_at,
|
|
390
|
-
creator_id=g.user.id,
|
|
391
|
-
content="Test highlight",
|
|
392
|
-
completed=None,
|
|
393
|
-
comments_count=0,
|
|
394
|
-
)
|
|
395
|
-
highlight_entry.save()
|
|
396
|
-
|
|
397
|
-
response = flask_client.post(
|
|
398
|
-
"/api/v1/views/widgets/highlights/comments/create",
|
|
399
|
-
data=json.dumps({
|
|
400
|
-
"view_id": view_id,
|
|
401
|
-
"index": 0,
|
|
402
|
-
"highlight_created_at": highlight_created_at.timestamp(),
|
|
403
|
-
"content": "Test comment",
|
|
404
|
-
}),
|
|
405
|
-
content_type="application/json",
|
|
406
|
-
)
|
|
407
|
-
assert response.status_code == 200
|
|
408
|
-
assert response.json["status"] == "ok"
|
|
409
|
-
assert response.json["response"]["content"] == "Test comment"
|
|
410
|
-
|
|
411
|
-
updated_highlight = WidgetHighlights.objects(view_id=UUID(
|
|
412
|
-
view_id), index=0, created_at=highlight_created_at).first()
|
|
413
|
-
assert updated_highlight.comments_count == 1
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
def test_delete_comment_should_decrement_comments_count(flask_client):
|
|
417
|
-
view_id = str(uuid4())
|
|
418
|
-
highlight_created_at = datetime.now(UTC)
|
|
419
|
-
comment_created_at = datetime.now(UTC)
|
|
420
|
-
highlight_entry = WidgetHighlights(
|
|
421
|
-
view_id=UUID(view_id),
|
|
422
|
-
index=0,
|
|
423
|
-
created_at=highlight_created_at,
|
|
424
|
-
creator_id=g.user.id,
|
|
425
|
-
content="Test highlight",
|
|
426
|
-
completed=None,
|
|
427
|
-
comments_count=1,
|
|
428
|
-
)
|
|
429
|
-
highlight_entry.save()
|
|
430
|
-
comment_entry = WidgetComment(
|
|
431
|
-
view_id=UUID(view_id),
|
|
432
|
-
index=0,
|
|
433
|
-
highlight_at=highlight_created_at,
|
|
434
|
-
created_at=comment_created_at,
|
|
435
|
-
creator_id=g.user.id,
|
|
436
|
-
content="Test comment",
|
|
437
|
-
)
|
|
438
|
-
comment_entry.save()
|
|
439
|
-
|
|
440
|
-
response = flask_client.post(
|
|
441
|
-
"/api/v1/views/widgets/highlights/comments/delete",
|
|
442
|
-
data=json.dumps({
|
|
443
|
-
"view_id": view_id,
|
|
444
|
-
"index": 0,
|
|
445
|
-
"highlight_created_at": highlight_created_at.timestamp(),
|
|
446
|
-
"created_at": comment_created_at.timestamp(),
|
|
447
|
-
}),
|
|
448
|
-
content_type="application/json",
|
|
449
|
-
)
|
|
450
|
-
assert response.status_code == 200
|
|
451
|
-
assert response.json["status"] == "ok"
|
|
452
|
-
|
|
453
|
-
updated_highlight = WidgetHighlights.objects(view_id=UUID(
|
|
454
|
-
view_id), index=0, created_at=highlight_created_at).first()
|
|
455
|
-
assert updated_highlight.comments_count == 0
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
@patch("argus.backend.service.views_widgets.highlights.HighlightsService._send_highlight_notifications")
|
|
459
|
-
def test_update_comment_should_modify_content(notification, flask_client):
|
|
460
|
-
view_id = str(uuid4())
|
|
461
|
-
highlight_created_at = datetime.now(UTC)
|
|
462
|
-
comment_created_at = datetime.now(UTC)
|
|
463
|
-
comment_content = "Original comment"
|
|
464
|
-
updated_content = "Updated comment"
|
|
465
|
-
|
|
466
|
-
highlight_entry = WidgetHighlights(
|
|
467
|
-
view_id=UUID(view_id),
|
|
468
|
-
index=0,
|
|
469
|
-
created_at=highlight_created_at,
|
|
470
|
-
creator_id=g.user.id,
|
|
471
|
-
content="Test highlight",
|
|
472
|
-
completed=None,
|
|
473
|
-
comments_count=1,
|
|
474
|
-
)
|
|
475
|
-
highlight_entry.save()
|
|
476
|
-
comment_entry = WidgetComment(
|
|
477
|
-
view_id=UUID(view_id),
|
|
478
|
-
index=0,
|
|
479
|
-
highlight_at=highlight_created_at,
|
|
480
|
-
created_at=comment_created_at,
|
|
481
|
-
creator_id=g.user.id,
|
|
482
|
-
content=comment_content,
|
|
483
|
-
)
|
|
484
|
-
comment_entry.save()
|
|
485
|
-
|
|
486
|
-
response = flask_client.post(
|
|
487
|
-
"/api/v1/views/widgets/highlights/comments/update",
|
|
488
|
-
data=json.dumps({
|
|
489
|
-
"view_id": view_id,
|
|
490
|
-
"index": 0,
|
|
491
|
-
"highlight_created_at": highlight_created_at.timestamp(),
|
|
492
|
-
"created_at": comment_created_at.timestamp(),
|
|
493
|
-
"content": updated_content,
|
|
494
|
-
}),
|
|
495
|
-
content_type="application/json",
|
|
496
|
-
)
|
|
497
|
-
assert response.status_code == 200
|
|
498
|
-
assert response.json["status"] == "ok"
|
|
499
|
-
assert response.json["response"]["content"] == updated_content
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
def test_get_comments_should_return_list_of_comments(flask_client):
|
|
503
|
-
view_id = str(uuid4())
|
|
504
|
-
highlight_created_at = datetime.now(UTC)
|
|
505
|
-
comment_created_at = datetime.now(UTC)
|
|
506
|
-
highlight_entry = WidgetHighlights(
|
|
507
|
-
view_id=UUID(view_id),
|
|
508
|
-
index=0,
|
|
509
|
-
created_at=highlight_created_at,
|
|
510
|
-
creator_id=g.user.id,
|
|
511
|
-
content="Test highlight",
|
|
512
|
-
completed=None,
|
|
513
|
-
comments_count=1,
|
|
514
|
-
)
|
|
515
|
-
highlight_entry.save()
|
|
516
|
-
comment_entry = WidgetComment(
|
|
517
|
-
view_id=UUID(view_id),
|
|
518
|
-
index=0,
|
|
519
|
-
highlight_at=highlight_created_at,
|
|
520
|
-
created_at=comment_created_at,
|
|
521
|
-
creator_id=g.user.id,
|
|
522
|
-
content="Test comment",
|
|
523
|
-
)
|
|
524
|
-
comment_entry.save()
|
|
525
|
-
|
|
526
|
-
response = flask_client.get(
|
|
527
|
-
f"/api/v1/views/widgets/highlights/comments?view_id={view_id}&index=0&created_at={highlight_created_at.timestamp()}")
|
|
528
|
-
assert response.status_code == 200
|
|
529
|
-
assert response.json["status"] == "ok"
|
|
530
|
-
comments = response.json["response"]
|
|
531
|
-
assert len(comments) == 1
|
|
532
|
-
assert comments[0]["content"] == "Test comment"
|
argus/backend/util/common.py
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
from itertools import islice
|
|
2
|
-
import logging
|
|
3
|
-
from typing import Callable, Iterable
|
|
4
|
-
from uuid import UUID
|
|
5
|
-
|
|
6
|
-
from flask import Request, Response, g
|
|
7
|
-
|
|
8
|
-
from argus.backend.models.web import User
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
LOGGER = logging.getLogger(__name__)
|
|
12
|
-
FlaskView = Callable[..., Response]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def first(iterable, value, key: Callable = None, predicate: Callable = None):
|
|
16
|
-
for elem in iterable:
|
|
17
|
-
if predicate and predicate(elem, value):
|
|
18
|
-
return elem
|
|
19
|
-
elif key and key(elem) == value:
|
|
20
|
-
return elem
|
|
21
|
-
elif elem == value:
|
|
22
|
-
return elem
|
|
23
|
-
return None
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def chunk(iterable: Iterable, slice_size=90):
|
|
27
|
-
it = iter(iterable)
|
|
28
|
-
return iter(lambda: list(islice(it, slice_size)), [])
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def check_scheduled_test(test, group, testname):
|
|
32
|
-
return testname in (f"{group}/{test}", test)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def strip_html_tags(text: str):
|
|
36
|
-
return text.replace("<", "<").replace(">", ">")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def convert_str_list_to_uuid(lst: list[str]) -> list[UUID]:
|
|
40
|
-
return [UUID(s) for s in lst]
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def get_payload(client_request: Request) -> dict:
|
|
44
|
-
if not client_request.is_json:
|
|
45
|
-
raise Exception(
|
|
46
|
-
"Content-Type mismatch, expected application/json, got:",
|
|
47
|
-
client_request.content_type
|
|
48
|
-
)
|
|
49
|
-
request_payload = client_request.get_json()
|
|
50
|
-
|
|
51
|
-
return request_payload
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def current_user() -> User:
|
|
55
|
-
return g.user
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def get_build_number(build_job_url: str) -> int | None:
|
|
59
|
-
build_number = build_job_url.rstrip("/").split("/")[-1] if build_job_url else -1
|
|
60
|
-
if build_number:
|
|
61
|
-
try:
|
|
62
|
-
return int(build_number)
|
|
63
|
-
except ValueError:
|
|
64
|
-
LOGGER.error("Error parsing build number from %s: got %s as build_number", build_job_url, build_number)
|
|
65
|
-
return None
|
argus/backend/util/config.py
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
|
|
4
|
-
import yaml
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
LOGGER = logging.getLogger(__name__)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Config:
|
|
11
|
-
CONFIG = None
|
|
12
|
-
CONFIG_PATHS = [
|
|
13
|
-
Path(__file__).parents[3] / "config" / "argus_web.yaml",
|
|
14
|
-
Path("argus_web.yaml"),
|
|
15
|
-
Path("../config/argus_web.yaml"),
|
|
16
|
-
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
@classmethod
|
|
20
|
-
def locate_argus_web_config(cls) -> Path:
|
|
21
|
-
for config in cls.CONFIG_PATHS:
|
|
22
|
-
if config.exists():
|
|
23
|
-
return config
|
|
24
|
-
else:
|
|
25
|
-
LOGGER.debug("Tried %s as config, not found.", config)
|
|
26
|
-
|
|
27
|
-
raise Exception("Failed to locate web application config file!")
|
|
28
|
-
|
|
29
|
-
@classmethod
|
|
30
|
-
def load_yaml_config(cls) -> dict:
|
|
31
|
-
if cls.CONFIG:
|
|
32
|
-
return cls.CONFIG
|
|
33
|
-
path = cls.locate_argus_web_config()
|
|
34
|
-
with open(path, "rt", encoding="utf-8") as file:
|
|
35
|
-
config = yaml.safe_load(file)
|
|
36
|
-
|
|
37
|
-
cls.CONFIG = config
|
|
38
|
-
return config
|
argus/backend/util/encoders.py
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
import logging
|
|
3
|
-
from json.encoder import JSONEncoder
|
|
4
|
-
from uuid import UUID
|
|
5
|
-
|
|
6
|
-
from flask.json.provider import DefaultJSONProvider
|
|
7
|
-
import cassandra.cqlengine.usertype as ut
|
|
8
|
-
import cassandra.cqlengine.models as m
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
LOGGER = logging.getLogger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ArgusJSONEncoder(JSONEncoder):
|
|
15
|
-
def default(self, o):
|
|
16
|
-
match o:
|
|
17
|
-
case UUID():
|
|
18
|
-
return str(o)
|
|
19
|
-
case ut.UserType():
|
|
20
|
-
return dict(o.items())
|
|
21
|
-
case m.Model():
|
|
22
|
-
return dict(o.items())
|
|
23
|
-
case datetime():
|
|
24
|
-
return o.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
25
|
-
case _:
|
|
26
|
-
return super().default(o)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class ArgusJSONProvider(DefaultJSONProvider):
|
|
30
|
-
|
|
31
|
-
@staticmethod
|
|
32
|
-
def process_nested_dicts(o: dict):
|
|
33
|
-
for k, v in o.items():
|
|
34
|
-
if isinstance(v, dict):
|
|
35
|
-
o[k] = {str(key): val for key, val in v.items()}
|
|
36
|
-
return o
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def default(cls, o):
|
|
40
|
-
match o:
|
|
41
|
-
case UUID():
|
|
42
|
-
return str(o)
|
|
43
|
-
case ut.UserType():
|
|
44
|
-
o = {str(k): v for k, v in o.items()}
|
|
45
|
-
o = cls.process_nested_dicts(o)
|
|
46
|
-
return o
|
|
47
|
-
case m.Model():
|
|
48
|
-
o = {str(k): v for k, v in o.items()}
|
|
49
|
-
o = cls.process_nested_dicts(o)
|
|
50
|
-
return o
|
|
51
|
-
case dict():
|
|
52
|
-
return {str(k): v for k, v in o.items()}
|
|
53
|
-
case datetime():
|
|
54
|
-
return o.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
55
|
-
case _:
|
|
56
|
-
return super().default(o)
|