wbwriter 2.2.1__py2.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.
Potentially problematic release.
This version of wbwriter might be problematic. Click here for more details.
- wbwriter/__init__.py +1 -0
- wbwriter/admin.py +142 -0
- wbwriter/apps.py +5 -0
- wbwriter/dynamic_preferences_registry.py +15 -0
- wbwriter/factories/__init__.py +13 -0
- wbwriter/factories/article.py +181 -0
- wbwriter/factories/meta_information.py +29 -0
- wbwriter/filters/__init__.py +2 -0
- wbwriter/filters/article.py +47 -0
- wbwriter/filters/metainformationinstance.py +24 -0
- wbwriter/migrations/0001_initial_squashed_squashed_0008_alter_article_author_alter_article_feedback_contact_and_more.py +653 -0
- wbwriter/migrations/0009_dependantarticle.py +41 -0
- wbwriter/migrations/0010_alter_article_options.py +20 -0
- wbwriter/migrations/0011_auto_20240103_0953.py +39 -0
- wbwriter/migrations/__init__.py +0 -0
- wbwriter/models/__init__.py +9 -0
- wbwriter/models/article.py +1179 -0
- wbwriter/models/article_type.py +59 -0
- wbwriter/models/block.py +24 -0
- wbwriter/models/block_parameter.py +19 -0
- wbwriter/models/in_editor_template.py +102 -0
- wbwriter/models/meta_information.py +87 -0
- wbwriter/models/mixins.py +9 -0
- wbwriter/models/publication_models.py +170 -0
- wbwriter/models/style.py +13 -0
- wbwriter/models/template.py +34 -0
- wbwriter/pdf_generator.py +172 -0
- wbwriter/publication_parser.py +258 -0
- wbwriter/serializers/__init__.py +28 -0
- wbwriter/serializers/article.py +359 -0
- wbwriter/serializers/article_type.py +14 -0
- wbwriter/serializers/in_editor_template.py +37 -0
- wbwriter/serializers/meta_information.py +67 -0
- wbwriter/serializers/publication.py +82 -0
- wbwriter/templatetags/__init__.py +0 -0
- wbwriter/templatetags/writer.py +72 -0
- wbwriter/tests/__init__.py +0 -0
- wbwriter/tests/conftest.py +32 -0
- wbwriter/tests/signals.py +23 -0
- wbwriter/tests/test_filter.py +58 -0
- wbwriter/tests/test_model.py +591 -0
- wbwriter/tests/test_writer.py +38 -0
- wbwriter/tests/tests.py +18 -0
- wbwriter/typings.py +23 -0
- wbwriter/urls.py +83 -0
- wbwriter/viewsets/__init__.py +22 -0
- wbwriter/viewsets/article.py +270 -0
- wbwriter/viewsets/article_type.py +49 -0
- wbwriter/viewsets/buttons.py +61 -0
- wbwriter/viewsets/display/__init__.py +6 -0
- wbwriter/viewsets/display/article.py +404 -0
- wbwriter/viewsets/display/article_type.py +27 -0
- wbwriter/viewsets/display/in_editor_template.py +39 -0
- wbwriter/viewsets/display/meta_information.py +37 -0
- wbwriter/viewsets/display/meta_information_instance.py +28 -0
- wbwriter/viewsets/display/publication.py +55 -0
- wbwriter/viewsets/endpoints/__init__.py +2 -0
- wbwriter/viewsets/endpoints/article.py +12 -0
- wbwriter/viewsets/endpoints/meta_information.py +14 -0
- wbwriter/viewsets/in_editor_template.py +68 -0
- wbwriter/viewsets/menu.py +42 -0
- wbwriter/viewsets/meta_information.py +51 -0
- wbwriter/viewsets/meta_information_instance.py +48 -0
- wbwriter/viewsets/publication.py +117 -0
- wbwriter/viewsets/titles/__init__.py +2 -0
- wbwriter/viewsets/titles/publication_title_config.py +18 -0
- wbwriter/viewsets/titles/reviewer_article_title_config.py +6 -0
- wbwriter-2.2.1.dist-info/METADATA +8 -0
- wbwriter-2.2.1.dist-info/RECORD +70 -0
- wbwriter-2.2.1.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from django.forms.models import model_to_dict
|
|
5
|
+
from django_fsm import has_transition_perm
|
|
6
|
+
from wbcore.contrib.authentication.factories import UserFactory
|
|
7
|
+
from wbcore.contrib.authentication.models import Permission, User
|
|
8
|
+
from wbwriter.factories import (
|
|
9
|
+
ArticleFactory,
|
|
10
|
+
ArticleTypeFactory,
|
|
11
|
+
DependantArticleFactory,
|
|
12
|
+
MetaInformationInstanceFactory,
|
|
13
|
+
)
|
|
14
|
+
from wbwriter.models import ArticleType, Publication
|
|
15
|
+
from wbwriter.models.article import (
|
|
16
|
+
Article,
|
|
17
|
+
DependantArticle,
|
|
18
|
+
can_access_article,
|
|
19
|
+
can_administrate_article,
|
|
20
|
+
can_edit_article_content,
|
|
21
|
+
can_edit_article_meta_data,
|
|
22
|
+
can_edit_article_type,
|
|
23
|
+
can_request_peer_review,
|
|
24
|
+
generate_publications,
|
|
25
|
+
)
|
|
26
|
+
from wbwriter.models.meta_information import MetaInformationInstance
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.django_db
|
|
30
|
+
class TestArticleTransitions:
|
|
31
|
+
@pytest.mark.parametrize("author", [True, False])
|
|
32
|
+
def test_requestfeedback(self, author):
|
|
33
|
+
user = UserFactory(is_superuser=False)
|
|
34
|
+
if author:
|
|
35
|
+
article = ArticleFactory(status=Article.Status.DRAFT, author=user.profile)
|
|
36
|
+
assert has_transition_perm(article.requestfeedback, user) is True
|
|
37
|
+
else:
|
|
38
|
+
article = ArticleFactory(status=Article.Status.DRAFT)
|
|
39
|
+
assert has_transition_perm(article.requestfeedback, user) is False
|
|
40
|
+
|
|
41
|
+
@pytest.mark.parametrize("reviewer", [True, False])
|
|
42
|
+
def test_submitfeedback(self, reviewer):
|
|
43
|
+
author_user = UserFactory(is_superuser=False)
|
|
44
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
45
|
+
article = ArticleFactory(
|
|
46
|
+
status=Article.Status.FEEDBACK,
|
|
47
|
+
author=author_user.profile,
|
|
48
|
+
reviewer=reviewer_user.profile if reviewer else UserFactory().profile,
|
|
49
|
+
)
|
|
50
|
+
if reviewer:
|
|
51
|
+
assert has_transition_perm(article.submitfeedback, reviewer_user) is True
|
|
52
|
+
assert has_transition_perm(article.submitfeedback, author_user) is False
|
|
53
|
+
else:
|
|
54
|
+
article = ArticleFactory(status=Article.Status.FEEDBACK)
|
|
55
|
+
assert has_transition_perm(article.submitfeedback, reviewer_user) is False
|
|
56
|
+
|
|
57
|
+
@pytest.mark.parametrize("author", [True, False])
|
|
58
|
+
def test_requestpeerreview(self, author):
|
|
59
|
+
author_user = UserFactory(is_superuser=False)
|
|
60
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
61
|
+
article_review_approved = ArticleFactory(
|
|
62
|
+
status=Article.Status.DRAFT,
|
|
63
|
+
author=author_user.profile if author else UserFactory().profile,
|
|
64
|
+
reviewer=reviewer_user.profile,
|
|
65
|
+
peer_reviewer_approved=True,
|
|
66
|
+
)
|
|
67
|
+
article_not_review_approved = ArticleFactory(
|
|
68
|
+
status=Article.Status.DRAFT,
|
|
69
|
+
author=author_user.profile if author else UserFactory().profile,
|
|
70
|
+
reviewer=reviewer_user.profile,
|
|
71
|
+
peer_reviewer_approved=False,
|
|
72
|
+
)
|
|
73
|
+
if author:
|
|
74
|
+
assert has_transition_perm(article_review_approved.requestpeerreview, author_user) is False
|
|
75
|
+
assert has_transition_perm(article_review_approved.requestpeerreview, reviewer_user) is False
|
|
76
|
+
assert has_transition_perm(article_not_review_approved.requestpeerreview, author_user) is True
|
|
77
|
+
else:
|
|
78
|
+
assert has_transition_perm(article_review_approved.requestpeerreview, author_user) is False
|
|
79
|
+
assert has_transition_perm(article_not_review_approved.requestpeerreview, author_user) is False
|
|
80
|
+
|
|
81
|
+
@pytest.mark.parametrize("author", [True, False])
|
|
82
|
+
def test_requestqareview(self, author):
|
|
83
|
+
author_user = UserFactory(is_superuser=False)
|
|
84
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
85
|
+
article_review_approved = ArticleFactory(
|
|
86
|
+
status=Article.Status.DRAFT,
|
|
87
|
+
author=author_user.profile if author else UserFactory().profile,
|
|
88
|
+
reviewer=reviewer_user.profile,
|
|
89
|
+
peer_reviewer_approved=True,
|
|
90
|
+
)
|
|
91
|
+
article_not_review_approved = ArticleFactory(
|
|
92
|
+
status=Article.Status.DRAFT,
|
|
93
|
+
author=author_user.profile if author else UserFactory().profile,
|
|
94
|
+
reviewer=reviewer_user.profile,
|
|
95
|
+
peer_reviewer_approved=False,
|
|
96
|
+
)
|
|
97
|
+
if author:
|
|
98
|
+
assert has_transition_perm(article_review_approved.requestqareview, author_user) is True
|
|
99
|
+
assert has_transition_perm(article_not_review_approved.requestqareview, author_user) is False
|
|
100
|
+
assert has_transition_perm(article_review_approved.requestqareview, reviewer_user) is False
|
|
101
|
+
else:
|
|
102
|
+
assert has_transition_perm(article_review_approved.requestqareview, author_user) is False
|
|
103
|
+
assert has_transition_perm(article_not_review_approved.requestqareview, author_user) is False
|
|
104
|
+
|
|
105
|
+
def test_peerapprove(self):
|
|
106
|
+
super_user = UserFactory(is_superuser=True)
|
|
107
|
+
author_user = UserFactory(is_superuser=False)
|
|
108
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
109
|
+
peer_reviewer_user_a = UserFactory(is_superuser=False)
|
|
110
|
+
peer_reviewer_user_b = UserFactory(is_superuser=False)
|
|
111
|
+
article_type_a = ArticleTypeFactory(peer_reviewers=[peer_reviewer_user_a.profile])
|
|
112
|
+
ArticleTypeFactory(peer_reviewers=[peer_reviewer_user_b.profile])
|
|
113
|
+
|
|
114
|
+
article = ArticleFactory(
|
|
115
|
+
status=Article.Status.PEER_REVIEW,
|
|
116
|
+
author=author_user.profile,
|
|
117
|
+
reviewer=reviewer_user.profile,
|
|
118
|
+
peer_reviewer=peer_reviewer_user_a.profile,
|
|
119
|
+
type=article_type_a,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
assert has_transition_perm(article.peerapprove, author_user) is False
|
|
123
|
+
assert has_transition_perm(article.peerapprove, reviewer_user) is False
|
|
124
|
+
assert has_transition_perm(article.peerapprove, peer_reviewer_user_b) is False
|
|
125
|
+
assert has_transition_perm(article.peerapprove, peer_reviewer_user_a) is True
|
|
126
|
+
assert has_transition_perm(article.peerapprove, super_user) is True
|
|
127
|
+
|
|
128
|
+
def test_peerreject(self):
|
|
129
|
+
super_user = UserFactory(is_superuser=True)
|
|
130
|
+
author_user = UserFactory(is_superuser=False)
|
|
131
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
132
|
+
peer_reviewer_user_a = UserFactory(is_superuser=False)
|
|
133
|
+
peer_reviewer_user_b = UserFactory(is_superuser=False)
|
|
134
|
+
ArticleTypeFactory(peer_reviewers=[peer_reviewer_user_b.profile])
|
|
135
|
+
article_type_a = ArticleTypeFactory(peer_reviewers=[peer_reviewer_user_a.profile])
|
|
136
|
+
|
|
137
|
+
article = ArticleFactory(
|
|
138
|
+
status=Article.Status.PEER_REVIEW,
|
|
139
|
+
author=author_user.profile,
|
|
140
|
+
reviewer=reviewer_user.profile,
|
|
141
|
+
peer_reviewer=peer_reviewer_user_a.profile,
|
|
142
|
+
type=article_type_a,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
assert has_transition_perm(article.peerapprove, author_user) is False
|
|
146
|
+
assert has_transition_perm(article.peerapprove, reviewer_user) is False
|
|
147
|
+
assert has_transition_perm(article.peerapprove, peer_reviewer_user_b) is False
|
|
148
|
+
assert has_transition_perm(article.peerapprove, peer_reviewer_user_a) is True
|
|
149
|
+
assert has_transition_perm(article.peerapprove, super_user) is True
|
|
150
|
+
|
|
151
|
+
def test_qa_reject(self):
|
|
152
|
+
super_user = UserFactory(is_superuser=True)
|
|
153
|
+
author_user = UserFactory(is_superuser=False)
|
|
154
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
155
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
156
|
+
qa_reviewer_user_a = UserFactory(is_superuser=False)
|
|
157
|
+
qa_reviewer_user_b = UserFactory(is_superuser=False)
|
|
158
|
+
ArticleTypeFactory(qa_reviewers=[qa_reviewer_user_b.profile])
|
|
159
|
+
|
|
160
|
+
article_type_a = ArticleTypeFactory(
|
|
161
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
162
|
+
qa_reviewers=[qa_reviewer_user_a.profile],
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
article = ArticleFactory(
|
|
166
|
+
status=Article.Status.QA_REVIEW,
|
|
167
|
+
author=author_user.profile,
|
|
168
|
+
reviewer=reviewer_user.profile,
|
|
169
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
170
|
+
qa_reviewer=qa_reviewer_user_a.profile,
|
|
171
|
+
type=article_type_a,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
assert has_transition_perm(article.qareject, author_user) is False
|
|
175
|
+
assert has_transition_perm(article.qareject, reviewer_user) is False
|
|
176
|
+
assert has_transition_perm(article.qareject, peer_reviewer_user) is False
|
|
177
|
+
assert has_transition_perm(article.qareject, qa_reviewer_user_b) is False
|
|
178
|
+
assert has_transition_perm(article.qareject, super_user) is True
|
|
179
|
+
assert has_transition_perm(article.qareject, qa_reviewer_user_a) is True
|
|
180
|
+
|
|
181
|
+
def test_qa_approve(self):
|
|
182
|
+
super_user = UserFactory(is_superuser=True)
|
|
183
|
+
author_user = UserFactory(is_superuser=False)
|
|
184
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
185
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
186
|
+
qa_reviewer_user_a = UserFactory(is_superuser=False)
|
|
187
|
+
qa_reviewer_user_b = UserFactory(is_superuser=False)
|
|
188
|
+
ArticleTypeFactory(qa_reviewers=[qa_reviewer_user_b.profile])
|
|
189
|
+
|
|
190
|
+
article_type_a = ArticleTypeFactory(
|
|
191
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
192
|
+
qa_reviewers=[qa_reviewer_user_a.profile],
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
article = ArticleFactory(
|
|
196
|
+
status=Article.Status.QA_REVIEW,
|
|
197
|
+
author=author_user.profile,
|
|
198
|
+
reviewer=reviewer_user.profile,
|
|
199
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
200
|
+
qa_reviewer=qa_reviewer_user_a.profile,
|
|
201
|
+
type=article_type_a,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
assert has_transition_perm(article.qaapprove, author_user) is False
|
|
205
|
+
assert has_transition_perm(article.qaapprove, reviewer_user) is False
|
|
206
|
+
assert has_transition_perm(article.qaapprove, peer_reviewer_user) is False
|
|
207
|
+
assert has_transition_perm(article.qaapprove, qa_reviewer_user_b) is False
|
|
208
|
+
assert has_transition_perm(article.qaapprove, super_user) is True
|
|
209
|
+
assert has_transition_perm(article.qaapprove, qa_reviewer_user_a) is True
|
|
210
|
+
|
|
211
|
+
def test_authorreject(self):
|
|
212
|
+
super_user = UserFactory(is_superuser=True)
|
|
213
|
+
author_user = UserFactory(is_superuser=False)
|
|
214
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
215
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
216
|
+
qa_reviewer_user = UserFactory(is_superuser=False)
|
|
217
|
+
article_type_a = ArticleTypeFactory(
|
|
218
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
219
|
+
qa_reviewers=[qa_reviewer_user.profile],
|
|
220
|
+
)
|
|
221
|
+
article = ArticleFactory(
|
|
222
|
+
status=Article.Status.AUTHOR_APPROVAL,
|
|
223
|
+
author=author_user.profile,
|
|
224
|
+
reviewer=reviewer_user.profile,
|
|
225
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
226
|
+
qa_reviewer=qa_reviewer_user.profile,
|
|
227
|
+
type=article_type_a,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
assert has_transition_perm(article.authorreject, reviewer_user) is False
|
|
231
|
+
assert has_transition_perm(article.authorreject, peer_reviewer_user) is False
|
|
232
|
+
assert has_transition_perm(article.authorreject, qa_reviewer_user) is False
|
|
233
|
+
assert has_transition_perm(article.authorreject, super_user) is True
|
|
234
|
+
assert has_transition_perm(article.authorreject, author_user) is True
|
|
235
|
+
|
|
236
|
+
def test_authorapprove(self):
|
|
237
|
+
super_user = UserFactory(is_superuser=True)
|
|
238
|
+
author_user = UserFactory(is_superuser=False)
|
|
239
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
240
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
241
|
+
qa_reviewer_user = UserFactory(is_superuser=False)
|
|
242
|
+
article_type_a = ArticleTypeFactory(
|
|
243
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
244
|
+
qa_reviewers=[qa_reviewer_user.profile],
|
|
245
|
+
)
|
|
246
|
+
article = ArticleFactory(
|
|
247
|
+
status=Article.Status.AUTHOR_APPROVAL,
|
|
248
|
+
author=author_user.profile,
|
|
249
|
+
reviewer=reviewer_user.profile,
|
|
250
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
251
|
+
qa_reviewer=qa_reviewer_user.profile,
|
|
252
|
+
type=article_type_a,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
assert has_transition_perm(article.authorapprove, reviewer_user) is False
|
|
256
|
+
assert has_transition_perm(article.authorapprove, peer_reviewer_user) is False
|
|
257
|
+
assert has_transition_perm(article.authorapprove, qa_reviewer_user) is False
|
|
258
|
+
assert has_transition_perm(article.authorapprove, super_user) is True
|
|
259
|
+
assert has_transition_perm(article.authorapprove, author_user) is True
|
|
260
|
+
|
|
261
|
+
def test_publish(self):
|
|
262
|
+
super_user = UserFactory(is_superuser=True)
|
|
263
|
+
author_user = UserFactory(is_superuser=False)
|
|
264
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
265
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
266
|
+
qa_reviewer_user = UserFactory(is_superuser=False)
|
|
267
|
+
can_publish_user: User = UserFactory(is_superuser=False)
|
|
268
|
+
can_publish_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
269
|
+
|
|
270
|
+
article_type = ArticleTypeFactory(
|
|
271
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
272
|
+
qa_reviewers=[qa_reviewer_user.profile],
|
|
273
|
+
label="one-off-article",
|
|
274
|
+
)
|
|
275
|
+
article = ArticleFactory(
|
|
276
|
+
status=Article.Status.APPROVED,
|
|
277
|
+
author=author_user.profile,
|
|
278
|
+
reviewer=reviewer_user.profile,
|
|
279
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
280
|
+
qa_reviewer=qa_reviewer_user.profile,
|
|
281
|
+
type=article_type,
|
|
282
|
+
)
|
|
283
|
+
assert has_transition_perm(article.publish, reviewer_user) is False
|
|
284
|
+
assert has_transition_perm(article.publish, peer_reviewer_user) is False
|
|
285
|
+
assert has_transition_perm(article.publish, qa_reviewer_user) is False
|
|
286
|
+
assert has_transition_perm(article.publish, author_user) is False
|
|
287
|
+
assert has_transition_perm(article.publish, super_user) is True
|
|
288
|
+
assert has_transition_perm(article.publish, can_publish_user) is True
|
|
289
|
+
|
|
290
|
+
def test_unpublish(self):
|
|
291
|
+
super_user = UserFactory(is_superuser=True)
|
|
292
|
+
author_user = UserFactory(is_superuser=False)
|
|
293
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
294
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
295
|
+
qa_reviewer_user = UserFactory(is_superuser=False)
|
|
296
|
+
can_publish_user: User = UserFactory(is_superuser=False)
|
|
297
|
+
can_publish_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
298
|
+
|
|
299
|
+
article_type = ArticleTypeFactory(
|
|
300
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
301
|
+
qa_reviewers=[qa_reviewer_user.profile],
|
|
302
|
+
label="one-off-article",
|
|
303
|
+
)
|
|
304
|
+
article = ArticleFactory(
|
|
305
|
+
status=Article.Status.PUBLISHED,
|
|
306
|
+
author=author_user.profile,
|
|
307
|
+
reviewer=reviewer_user.profile,
|
|
308
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
309
|
+
qa_reviewer=qa_reviewer_user.profile,
|
|
310
|
+
type=article_type,
|
|
311
|
+
)
|
|
312
|
+
assert has_transition_perm(article.unpublish, reviewer_user) is False
|
|
313
|
+
assert has_transition_perm(article.unpublish, peer_reviewer_user) is False
|
|
314
|
+
assert has_transition_perm(article.unpublish, qa_reviewer_user) is False
|
|
315
|
+
assert has_transition_perm(article.unpublish, author_user) is False
|
|
316
|
+
assert has_transition_perm(article.unpublish, super_user) is True
|
|
317
|
+
assert has_transition_perm(article.unpublish, can_publish_user) is True
|
|
318
|
+
|
|
319
|
+
def test_authorrevise(self):
|
|
320
|
+
super_user = UserFactory(is_superuser=True)
|
|
321
|
+
author_user = UserFactory(is_superuser=False)
|
|
322
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
323
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
324
|
+
qa_reviewer_user = UserFactory(is_superuser=False)
|
|
325
|
+
administrate_user: User = UserFactory(is_superuser=False)
|
|
326
|
+
administrate_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
327
|
+
|
|
328
|
+
article_type = ArticleTypeFactory(
|
|
329
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
330
|
+
qa_reviewers=[qa_reviewer_user.profile],
|
|
331
|
+
label="one-off-article",
|
|
332
|
+
)
|
|
333
|
+
article = ArticleFactory(
|
|
334
|
+
status=Article.Status.APPROVED,
|
|
335
|
+
author=author_user.profile,
|
|
336
|
+
reviewer=reviewer_user.profile,
|
|
337
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
338
|
+
qa_reviewer=qa_reviewer_user.profile,
|
|
339
|
+
type=article_type,
|
|
340
|
+
)
|
|
341
|
+
assert has_transition_perm(article.authorrevise, reviewer_user) is False
|
|
342
|
+
assert has_transition_perm(article.authorrevise, peer_reviewer_user) is False
|
|
343
|
+
assert has_transition_perm(article.authorrevise, qa_reviewer_user) is False
|
|
344
|
+
assert has_transition_perm(article.authorrevise, author_user) is True
|
|
345
|
+
assert has_transition_perm(article.authorrevise, super_user) is True
|
|
346
|
+
assert has_transition_perm(article.authorrevise, administrate_user) is True
|
|
347
|
+
|
|
348
|
+
def test_qarevise(self):
|
|
349
|
+
super_user = UserFactory(is_superuser=True)
|
|
350
|
+
author_user = UserFactory(is_superuser=False)
|
|
351
|
+
reviewer_user = UserFactory(is_superuser=False)
|
|
352
|
+
peer_reviewer_user = UserFactory(is_superuser=False)
|
|
353
|
+
qa_reviewer_user_a = UserFactory(is_superuser=False)
|
|
354
|
+
qa_reviewer_user_b = UserFactory(is_superuser=False)
|
|
355
|
+
administrate_user: User = UserFactory(is_superuser=False)
|
|
356
|
+
administrate_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
357
|
+
|
|
358
|
+
article_type = ArticleTypeFactory(
|
|
359
|
+
peer_reviewers=[peer_reviewer_user.profile],
|
|
360
|
+
qa_reviewers=[qa_reviewer_user_a.profile, qa_reviewer_user_b.profile],
|
|
361
|
+
label="one-off-article",
|
|
362
|
+
)
|
|
363
|
+
article = ArticleFactory(
|
|
364
|
+
status=Article.Status.APPROVED,
|
|
365
|
+
author=author_user.profile,
|
|
366
|
+
reviewer=reviewer_user.profile,
|
|
367
|
+
peer_reviewer=peer_reviewer_user.profile,
|
|
368
|
+
qa_reviewer=qa_reviewer_user_a.profile,
|
|
369
|
+
type=article_type,
|
|
370
|
+
)
|
|
371
|
+
assert has_transition_perm(article.qarevise, reviewer_user) is False
|
|
372
|
+
assert has_transition_perm(article.qarevise, peer_reviewer_user) is False
|
|
373
|
+
assert has_transition_perm(article.qarevise, qa_reviewer_user_a) is True
|
|
374
|
+
assert has_transition_perm(article.qarevise, qa_reviewer_user_b) is True
|
|
375
|
+
assert has_transition_perm(article.qarevise, author_user) is False
|
|
376
|
+
assert has_transition_perm(article.qarevise, super_user) is True
|
|
377
|
+
assert has_transition_perm(article.qarevise, administrate_user) is True
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@pytest.mark.django_db
|
|
381
|
+
class TestArticlePermissions:
|
|
382
|
+
def test_can_administrate_article(self):
|
|
383
|
+
super_user: User = UserFactory(is_superuser=True)
|
|
384
|
+
article_admin_user: User = UserFactory(is_superuser=False)
|
|
385
|
+
article_admin_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
386
|
+
unalligned_user: User = UserFactory(is_superuser=False)
|
|
387
|
+
|
|
388
|
+
article = ArticleFactory()
|
|
389
|
+
assert can_administrate_article(article, super_user)
|
|
390
|
+
assert can_administrate_article(article, article_admin_user)
|
|
391
|
+
assert not can_administrate_article(article, unalligned_user)
|
|
392
|
+
|
|
393
|
+
def test_can_publish_articles(self):
|
|
394
|
+
super_user: User = UserFactory(is_superuser=True)
|
|
395
|
+
article_admin_user: User = UserFactory(is_superuser=False)
|
|
396
|
+
article_admin_user.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
397
|
+
unalligned_user: User = UserFactory(is_superuser=False)
|
|
398
|
+
|
|
399
|
+
article: Article = ArticleFactory()
|
|
400
|
+
assert can_administrate_article(article, super_user)
|
|
401
|
+
assert can_administrate_article(article, article_admin_user)
|
|
402
|
+
assert not can_administrate_article(article, unalligned_user)
|
|
403
|
+
|
|
404
|
+
@patch.object(Publication, "create_or_update_from_parser_and_object")
|
|
405
|
+
def test_can_be_published(self, mock_fct):
|
|
406
|
+
article_a: Article = ArticleFactory(type=ArticleTypeFactory(label="One Off Article"))
|
|
407
|
+
|
|
408
|
+
assert article_a.can_be_published() is False
|
|
409
|
+
generate_publications(article_a.id)
|
|
410
|
+
assert mock_fct.call_count == 0
|
|
411
|
+
|
|
412
|
+
article_a.status = Article.Status.APPROVED
|
|
413
|
+
article_a.save()
|
|
414
|
+
assert article_a.can_be_published()
|
|
415
|
+
generate_publications(article_a.id)
|
|
416
|
+
assert mock_fct.call_count == 1
|
|
417
|
+
|
|
418
|
+
article_b: Article = ArticleFactory(
|
|
419
|
+
status=Article.Status.APPROVED, type=ArticleTypeFactory(label="Deep Dive Article")
|
|
420
|
+
)
|
|
421
|
+
article_c: Article = ArticleFactory(
|
|
422
|
+
status=Article.Status.APPROVED, type=ArticleTypeFactory(label="Mid Year Review")
|
|
423
|
+
)
|
|
424
|
+
article_d: Article = ArticleFactory(
|
|
425
|
+
status=Article.Status.APPROVED, type=ArticleTypeFactory(label="Unalligned Article")
|
|
426
|
+
)
|
|
427
|
+
assert article_a.can_be_published()
|
|
428
|
+
assert article_b.can_be_published()
|
|
429
|
+
assert article_c.can_be_published()
|
|
430
|
+
generate_publications(article_a.id)
|
|
431
|
+
generate_publications(article_b.id)
|
|
432
|
+
generate_publications(article_c.id)
|
|
433
|
+
assert mock_fct.call_count == 4
|
|
434
|
+
assert not article_d.can_be_published()
|
|
435
|
+
generate_publications(article_d.id)
|
|
436
|
+
assert mock_fct.call_count == 4
|
|
437
|
+
|
|
438
|
+
def test_can_access_article(self):
|
|
439
|
+
super_user: User = UserFactory(is_superuser=True)
|
|
440
|
+
reviewer_user: User = UserFactory(is_superuser=False)
|
|
441
|
+
is_qa_reviewer_user: User = UserFactory(is_superuser=False)
|
|
442
|
+
is_peer_reviewer_user: User = UserFactory(is_superuser=False)
|
|
443
|
+
user_can_administrate_article: User = UserFactory(is_superuser=False)
|
|
444
|
+
unalligned_user: User = UserFactory(is_superuser=False)
|
|
445
|
+
|
|
446
|
+
user_can_administrate_article.user_permissions.add(Permission.objects.get(codename="administrate_article"))
|
|
447
|
+
article_type: ArticleType = ArticleTypeFactory(
|
|
448
|
+
peer_reviewers=[is_peer_reviewer_user.profile], qa_reviewers=[is_qa_reviewer_user.profile]
|
|
449
|
+
)
|
|
450
|
+
article: Article = ArticleFactory(type=article_type, reviewer=reviewer_user.profile)
|
|
451
|
+
|
|
452
|
+
assert can_access_article(article, super_user)
|
|
453
|
+
# assert can_access_article(article, employee_user)
|
|
454
|
+
assert can_access_article(article, is_qa_reviewer_user)
|
|
455
|
+
assert can_access_article(article, is_peer_reviewer_user)
|
|
456
|
+
assert can_access_article(article, user_can_administrate_article)
|
|
457
|
+
assert not can_access_article(article, unalligned_user)
|
|
458
|
+
|
|
459
|
+
def test_can_edit_article_author(self):
|
|
460
|
+
self.test_can_administrate_article()
|
|
461
|
+
|
|
462
|
+
def test_can_edit_article_content(self):
|
|
463
|
+
user = UserFactory(is_superuser=False)
|
|
464
|
+
user_unalligned = UserFactory(is_superuser=False)
|
|
465
|
+
user_su = UserFactory(is_superuser=True)
|
|
466
|
+
|
|
467
|
+
article_type = ArticleTypeFactory(peer_reviewers=[user.profile], qa_reviewers=[user.profile])
|
|
468
|
+
|
|
469
|
+
article_draft: Article = ArticleFactory(status=Article.Status.DRAFT, author=user.profile)
|
|
470
|
+
article_feedback: Article = ArticleFactory(status=Article.Status.FEEDBACK, reviewer=user.profile)
|
|
471
|
+
article_peer_review: Article = ArticleFactory(
|
|
472
|
+
status=Article.Status.PEER_REVIEW, peer_reviewer=user.profile, type=article_type
|
|
473
|
+
)
|
|
474
|
+
article_qa_review: Article = ArticleFactory(
|
|
475
|
+
status=Article.Status.QA_REVIEW, qa_reviewer=user.profile, type=article_type
|
|
476
|
+
)
|
|
477
|
+
article_approved: Article = ArticleFactory(status=Article.Status.APPROVED)
|
|
478
|
+
|
|
479
|
+
assert can_edit_article_content(article_draft, user)
|
|
480
|
+
assert not can_edit_article_content(article_draft, user_unalligned)
|
|
481
|
+
assert can_edit_article_content(article_feedback, user)
|
|
482
|
+
assert not can_edit_article_content(article_feedback, user_unalligned)
|
|
483
|
+
assert can_edit_article_content(article_peer_review, user)
|
|
484
|
+
assert not can_edit_article_content(article_peer_review, user_unalligned)
|
|
485
|
+
assert can_edit_article_content(article_qa_review, user)
|
|
486
|
+
assert not can_edit_article_content(article_qa_review, user_unalligned)
|
|
487
|
+
assert can_edit_article_content(article_approved, user_su)
|
|
488
|
+
assert not can_edit_article_content(article_approved, user_unalligned)
|
|
489
|
+
|
|
490
|
+
def test_can_edit_article_meta_data(self):
|
|
491
|
+
user = UserFactory(is_superuser=False)
|
|
492
|
+
user_unalligned = UserFactory(is_superuser=False)
|
|
493
|
+
|
|
494
|
+
article_type = ArticleTypeFactory(peer_reviewers=[user.profile], qa_reviewers=[user.profile])
|
|
495
|
+
|
|
496
|
+
article_draft: Article = ArticleFactory(status=Article.Status.DRAFT, author=user.profile)
|
|
497
|
+
article_feedback: Article = ArticleFactory(status=Article.Status.FEEDBACK, reviewer=user.profile)
|
|
498
|
+
article_peer_review: Article = ArticleFactory(
|
|
499
|
+
status=Article.Status.PEER_REVIEW, peer_reviewer=user.profile, type=article_type
|
|
500
|
+
)
|
|
501
|
+
article_qa_review: Article = ArticleFactory(
|
|
502
|
+
status=Article.Status.QA_REVIEW, qa_reviewer=user.profile, type=article_type
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
assert can_edit_article_meta_data(article_draft, user=user)
|
|
506
|
+
assert not can_edit_article_meta_data(article_draft, user=user_unalligned)
|
|
507
|
+
assert can_edit_article_meta_data(article_feedback, user=user)
|
|
508
|
+
assert not can_edit_article_meta_data(article_feedback, user=user_unalligned)
|
|
509
|
+
assert can_edit_article_meta_data(article_peer_review, user=user)
|
|
510
|
+
assert not can_edit_article_meta_data(article_peer_review, user=user_unalligned)
|
|
511
|
+
assert can_edit_article_meta_data(article_qa_review, user=user)
|
|
512
|
+
assert not can_edit_article_meta_data(article_qa_review, user=user_unalligned)
|
|
513
|
+
|
|
514
|
+
def test_can_edit_article_type(self):
|
|
515
|
+
user = UserFactory(is_superuser=False)
|
|
516
|
+
user_unalligned = UserFactory(is_superuser=False)
|
|
517
|
+
article_draft: Article = ArticleFactory(status=Article.Status.DRAFT, author=user.profile)
|
|
518
|
+
article_feedback: Article = ArticleFactory(status=Article.Status.FEEDBACK, author=user.profile)
|
|
519
|
+
|
|
520
|
+
assert can_edit_article_type(article_draft, user)
|
|
521
|
+
assert not can_edit_article_type(article_feedback, user)
|
|
522
|
+
assert not can_edit_article_type(article_draft, user_unalligned)
|
|
523
|
+
|
|
524
|
+
@pytest.mark.parametrize("peer_reviewer_approved", [True, False])
|
|
525
|
+
def test_can_request_peer_review(self, peer_reviewer_approved):
|
|
526
|
+
article = ArticleFactory(peer_reviewer_approved=peer_reviewer_approved)
|
|
527
|
+
if peer_reviewer_approved:
|
|
528
|
+
assert not can_request_peer_review(article)
|
|
529
|
+
else:
|
|
530
|
+
assert can_request_peer_review(article)
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
@pytest.mark.django_db
|
|
534
|
+
class TestArticleCloning:
|
|
535
|
+
def test_clone(self, user):
|
|
536
|
+
article = ArticleFactory()
|
|
537
|
+
article = Article.objects.get(
|
|
538
|
+
id=article.id
|
|
539
|
+
) # To get updated tag_detail_endpoint and tag_representation from db
|
|
540
|
+
meta_information_instance = MetaInformationInstanceFactory(article=article)
|
|
541
|
+
dependender_relationship = DependantArticleFactory(article=article)
|
|
542
|
+
dependendee_relationship = DependantArticleFactory(dependant_article=article)
|
|
543
|
+
assert Article.objects.count() == 3
|
|
544
|
+
assert DependantArticle.objects.count() == 2
|
|
545
|
+
assert MetaInformationInstance.objects.count() == 1
|
|
546
|
+
|
|
547
|
+
cloned_article = article.clone(user=user)
|
|
548
|
+
|
|
549
|
+
# Article was correctly cloned
|
|
550
|
+
article_dict = model_to_dict(article)
|
|
551
|
+
del article_dict["id"]
|
|
552
|
+
del article_dict["teaser_image"]
|
|
553
|
+
article_clone_dict = model_to_dict(cloned_article)
|
|
554
|
+
assert article_clone_dict
|
|
555
|
+
del article_clone_dict["id"]
|
|
556
|
+
del article_clone_dict["teaser_image"]
|
|
557
|
+
article_dict["name"] += "_clone"
|
|
558
|
+
article_dict["slug"] += "-clone"
|
|
559
|
+
article_dict["title"] += " (Clone)"
|
|
560
|
+
article_dict["author"] = user.profile.id
|
|
561
|
+
assert article_dict == article_clone_dict
|
|
562
|
+
assert Article.objects.count() == 4
|
|
563
|
+
|
|
564
|
+
# Related dependant articles were correctly cloned
|
|
565
|
+
dependender_relationship_dict = model_to_dict(dependender_relationship)
|
|
566
|
+
del dependender_relationship_dict["id"]
|
|
567
|
+
dependender_relationship_clone_dict = model_to_dict(DependantArticle.objects.get(id=3))
|
|
568
|
+
assert dependender_relationship_clone_dict
|
|
569
|
+
del dependender_relationship_clone_dict["id"]
|
|
570
|
+
dependender_relationship_clone_dict["article"] = article.id
|
|
571
|
+
assert dependender_relationship_dict == dependender_relationship_clone_dict
|
|
572
|
+
|
|
573
|
+
dependendee_relationship_dict = model_to_dict(dependendee_relationship)
|
|
574
|
+
del dependendee_relationship_dict["id"]
|
|
575
|
+
dependendee_relationship_clone_dict = model_to_dict(DependantArticle.objects.get(id=4))
|
|
576
|
+
assert dependendee_relationship_clone_dict
|
|
577
|
+
del dependendee_relationship_clone_dict["id"]
|
|
578
|
+
dependendee_relationship_clone_dict["dependant_article"] = article.id
|
|
579
|
+
assert dependendee_relationship_dict == dependendee_relationship_clone_dict
|
|
580
|
+
|
|
581
|
+
assert DependantArticle.objects.count() == 4
|
|
582
|
+
|
|
583
|
+
# Related meta information instances were correctly cloned
|
|
584
|
+
meta_information_instance_dict = model_to_dict(meta_information_instance)
|
|
585
|
+
del meta_information_instance_dict["id"]
|
|
586
|
+
meta_information_instance_clone_dict = model_to_dict(MetaInformationInstance.objects.last())
|
|
587
|
+
assert meta_information_instance_clone_dict
|
|
588
|
+
del meta_information_instance_clone_dict["id"]
|
|
589
|
+
meta_information_instance_clone_dict["article"] = article.id
|
|
590
|
+
assert meta_information_instance_dict == meta_information_instance_clone_dict
|
|
591
|
+
assert MetaInformationInstance.objects.count() == 2
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from wbwriter.templatetags.writer import cite_article, table_of_contents
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@pytest.mark.django_db
|
|
6
|
+
class TestWriter:
|
|
7
|
+
def test_table_of_contents(self, article_factory):
|
|
8
|
+
article_dict = {"article": article_factory(title="Test Article Title", name="Test Article Name")}
|
|
9
|
+
toc = table_of_contents(article_dict, "ToC ")
|
|
10
|
+
test_toc = {
|
|
11
|
+
"title": "Test Article Title",
|
|
12
|
+
"custom_enumeration": True,
|
|
13
|
+
"anchor": "test-article-name",
|
|
14
|
+
"enumerator": None,
|
|
15
|
+
"level": 0,
|
|
16
|
+
"articles": [],
|
|
17
|
+
}
|
|
18
|
+
assert toc == test_toc
|
|
19
|
+
|
|
20
|
+
def test_table_of_contents_no_context(self):
|
|
21
|
+
no_article_dict = {"blog": "Some Blog"}
|
|
22
|
+
toc = table_of_contents(no_article_dict, "ToC ")
|
|
23
|
+
test_toc = {"not_working": "<i>Table of content is only rendered in the exported PDF Version.</i>"}
|
|
24
|
+
assert toc == test_toc
|
|
25
|
+
|
|
26
|
+
def test_cite_article(self, article_factory):
|
|
27
|
+
article = article_factory(title="Test Article Title", name="Test Article Name")
|
|
28
|
+
article_dict: dict = {"article": article}
|
|
29
|
+
ca = cite_article(article_dict, article.id)
|
|
30
|
+
test_ca = {"anchor": "test-article-name", "text": "(see Test Article Title)"}
|
|
31
|
+
assert ca == test_ca
|
|
32
|
+
|
|
33
|
+
def test_cite_article_no_context(self, article_factory):
|
|
34
|
+
article = article_factory()
|
|
35
|
+
no_article_dict = {"blog": "Some Blog"}
|
|
36
|
+
ca = cite_article(no_article_dict, article.id)
|
|
37
|
+
test_ca = {"not_working": "(article citations only work in a rendered pdf.)"}
|
|
38
|
+
assert ca == test_ca
|
wbwriter/tests/tests.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from wbcore.test import GenerateTest, default_config
|
|
3
|
+
|
|
4
|
+
config = {}
|
|
5
|
+
|
|
6
|
+
for key, value in default_config.items():
|
|
7
|
+
config[key] = list(
|
|
8
|
+
filter(
|
|
9
|
+
lambda x: x.__module__.startswith("wbwriter"),
|
|
10
|
+
value,
|
|
11
|
+
)
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.mark.django_db
|
|
16
|
+
@GenerateTest(config)
|
|
17
|
+
class TestProject:
|
|
18
|
+
pass
|
wbwriter/typings.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from dataclasses import asdict, dataclass
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class ArticleDTO:
|
|
9
|
+
name: str
|
|
10
|
+
slug: str
|
|
11
|
+
title: str
|
|
12
|
+
teaser_image: BytesIO | None
|
|
13
|
+
created: datetime
|
|
14
|
+
modified: datetime
|
|
15
|
+
content: dict[str, str]
|
|
16
|
+
is_private: bool
|
|
17
|
+
article_structure: dict[str, str]
|
|
18
|
+
status: str
|
|
19
|
+
meta_information: list[dict[str, Any]]
|
|
20
|
+
tags: list[int]
|
|
21
|
+
|
|
22
|
+
def to_dict(self):
|
|
23
|
+
return asdict(self)
|