wbcore 2.2.1__py2.py3-none-any.whl → 2.2.4__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.
Files changed (143) hide show
  1. wbcore/contrib/agenda/locale/de/LC_MESSAGES/django.po +113 -0
  2. wbcore/contrib/agenda/static/agenda/markdown/documentation/building.md +11 -0
  3. wbcore/contrib/agenda/static/agenda/markdown/documentation/conferenceroom.md +20 -0
  4. wbcore/contrib/authentication/fixtures/authentication.json +62 -0
  5. wbcore/contrib/authentication/locale/de/LC_MESSAGES/django.po +610 -0
  6. wbcore/contrib/authentication/templates/activate_confirm.html +12 -0
  7. wbcore/contrib/authentication/templates/base.html +135 -0
  8. wbcore/contrib/authentication/templates/email_base_template.html +335 -0
  9. wbcore/contrib/authentication/templates/password_reset_done.html +13 -0
  10. wbcore/contrib/authentication/templates/password_reset_email.html +11 -0
  11. wbcore/contrib/authentication/templates/password_reset_email_html.html +43 -0
  12. wbcore/contrib/authentication/templates/password_reset_form.html +23 -0
  13. wbcore/contrib/authentication/templates/password_reset_sent.html +11 -0
  14. wbcore/contrib/authentication/templates/reset_password.html +15 -0
  15. wbcore/contrib/authentication/templates/user_registration_email.html +37 -0
  16. wbcore/contrib/color/admin.py +28 -0
  17. wbcore/contrib/color/apps.py +5 -0
  18. wbcore/contrib/color/enums.py +17 -0
  19. wbcore/contrib/color/factories.py +10 -0
  20. wbcore/contrib/color/fields.py +29 -0
  21. wbcore/contrib/color/forms.py +13 -0
  22. wbcore/contrib/color/models.py +62 -0
  23. wbcore/contrib/color/tests/conftest.py +10 -0
  24. wbcore/contrib/color/tests/test_color_models.py +61 -0
  25. wbcore/contrib/color/tests/test_fields.py +25 -0
  26. wbcore/contrib/currency/fixtures/currency.yaml +1014 -0
  27. wbcore/contrib/currency/fixtures/currency_fx_rate.yaml +73585 -0
  28. wbcore/contrib/directory/fixtures/directory.json +3924 -0
  29. wbcore/contrib/directory/locale/de/LC_MESSAGES/django.po +1686 -0
  30. wbcore/contrib/directory/static/directory/markdown/documentation/address.md +38 -0
  31. wbcore/contrib/directory/static/directory/markdown/documentation/banking.md +54 -0
  32. wbcore/contrib/directory/static/directory/markdown/documentation/bankingentry.md +38 -0
  33. wbcore/contrib/directory/static/directory/markdown/documentation/clientmanagerrelationship.md +42 -0
  34. wbcore/contrib/directory/static/directory/markdown/documentation/company.md +52 -0
  35. wbcore/contrib/directory/static/directory/markdown/documentation/companytype.md +2 -0
  36. wbcore/contrib/directory/static/directory/markdown/documentation/customerstatus.md +2 -0
  37. wbcore/contrib/directory/static/directory/markdown/documentation/email.md +20 -0
  38. wbcore/contrib/directory/static/directory/markdown/documentation/employeecompany.md +34 -0
  39. wbcore/contrib/directory/static/directory/markdown/documentation/employerperson.md +43 -0
  40. wbcore/contrib/directory/static/directory/markdown/documentation/person.md +61 -0
  41. wbcore/contrib/directory/static/directory/markdown/documentation/position.md +2 -0
  42. wbcore/contrib/directory/static/directory/markdown/documentation/relationshiptype.md +2 -0
  43. wbcore/contrib/directory/static/directory/markdown/documentation/socialmedia.md +23 -0
  44. wbcore/contrib/directory/static/directory/markdown/documentation/specialization.md +2 -0
  45. wbcore/contrib/directory/static/directory/markdown/documentation/systememployee.md +31 -0
  46. wbcore/contrib/directory/static/directory/markdown/documentation/telephone.md +23 -0
  47. wbcore/contrib/directory/static/directory/markdown/documentation/telephonesearch.md +26 -0
  48. wbcore/contrib/directory/static/directory/markdown/documentation/userisclient.md +14 -0
  49. wbcore/contrib/directory/static/directory/markdown/documentation/userismanager.md +28 -0
  50. wbcore/contrib/directory/static/directory/markdown/documentation/website.md +20 -0
  51. wbcore/contrib/documents/fixtures/docments.json +135 -0
  52. wbcore/contrib/documents/locale/de/LC_MESSAGES/django.po +272 -0
  53. wbcore/contrib/documents/static/documents/markdown/documentation/document_types.md +21 -0
  54. wbcore/contrib/documents/static/documents/markdown/documentation/documents.md +18 -0
  55. wbcore/contrib/documents/static/documents/markdown/documentation/shareablelink.md +28 -0
  56. wbcore/contrib/documents/static/documents/markdown/documentation/shareablelinkaccess.md +20 -0
  57. wbcore/contrib/documents/tests/conftest.py +30 -0
  58. wbcore/contrib/documents/tests/test_models.py +144 -0
  59. wbcore/contrib/example_app/fixtures/example_app.json +7425 -0
  60. wbcore/contrib/example_app/tests/test_models/test_event.py +87 -0
  61. wbcore/contrib/example_app/tests/test_models/test_match.py +210 -0
  62. wbcore/contrib/example_app/tests/test_models/test_others.py +159 -0
  63. wbcore/contrib/example_app/tests/test_serializers/test_league_serializer.py +34 -0
  64. wbcore/contrib/example_app/tests/test_serializers/test_match_serializer.py +134 -0
  65. wbcore/contrib/example_app/tests/test_serializers/test_role_serializer.py +13 -0
  66. wbcore/contrib/example_app/tests/test_serializers/test_sport_serializer.py +14 -0
  67. wbcore/contrib/example_app/tests/test_serializers/test_stadium_serializer.py +14 -0
  68. wbcore/contrib/example_app/tests/test_serializers/test_team_result_serializer.py +30 -0
  69. wbcore/contrib/example_app/tests/test_serializers/test_team_serializer.py +70 -0
  70. wbcore/contrib/example_app/tests/test_viewsets/test_event_viewset.py +162 -0
  71. wbcore/contrib/example_app/tests/test_viewsets/test_league_viewset.py +84 -0
  72. wbcore/contrib/example_app/tests/test_viewsets/test_match_viewset.py +65 -0
  73. wbcore/contrib/example_app/tests/test_viewsets/test_person_viewset.py +166 -0
  74. wbcore/contrib/example_app/tests/test_viewsets/test_role_viewset.py +75 -0
  75. wbcore/contrib/example_app/tests/test_viewsets/test_sport_viewset.py +75 -0
  76. wbcore/contrib/example_app/tests/test_viewsets/test_stadium_viewset.py +75 -0
  77. wbcore/contrib/example_app/tests/test_viewsets/test_team_viewset.py +92 -0
  78. wbcore/contrib/example_app/tests/test_viewsets/test_teamresult_viewset.py +58 -0
  79. wbcore/contrib/example_app/tests/test_viewsets/test_utils_viewsets.py +124 -0
  80. wbcore/contrib/geography/fixtures/geography.json +13454 -0
  81. wbcore/contrib/geography/static/geography/markdown/documentation/geography.md +16 -0
  82. wbcore/contrib/guardian/apps.py +6 -0
  83. wbcore/contrib/guardian/configurations.py +3 -0
  84. wbcore/contrib/guardian/filters.py +21 -0
  85. wbcore/contrib/guardian/tasks.py +10 -0
  86. wbcore/contrib/guardian/urls.py +12 -0
  87. wbcore/contrib/guardian/utils.py +124 -0
  88. wbcore/contrib/io/fixtures/io.json +145 -0
  89. wbcore/contrib/io/locale/de/LC_MESSAGES/django.po +52 -0
  90. wbcore/contrib/notifications/locale/de/LC_MESSAGES/django.po +60 -0
  91. wbcore/contrib/notifications/static/notifications/service-worker.js +1 -0
  92. wbcore/contrib/notifications/templates/notifications/notification_template.html +43 -0
  93. wbcore/contrib/notifications/viewsets/configs/notification_types.py +27 -0
  94. wbcore/contrib/notifications/viewsets/configs/notifications.py +85 -0
  95. wbcore/contrib/workflow/fixtures/workflow.json +612 -0
  96. wbcore/contrib/workflow/locale/de/LC_MESSAGES/django.po +1289 -0
  97. wbcore/contrib/workflow/static/workflow/markdown/documentation/assignedprocessstep.md +33 -0
  98. wbcore/contrib/workflow/static/workflow/markdown/documentation/condition.md +24 -0
  99. wbcore/contrib/workflow/static/workflow/markdown/documentation/decisionstep.md +30 -0
  100. wbcore/contrib/workflow/static/workflow/markdown/documentation/emailstep.md +45 -0
  101. wbcore/contrib/workflow/static/workflow/markdown/documentation/finishstep.md +33 -0
  102. wbcore/contrib/workflow/static/workflow/markdown/documentation/joinstep.md +33 -0
  103. wbcore/contrib/workflow/static/workflow/markdown/documentation/process.md +33 -0
  104. wbcore/contrib/workflow/static/workflow/markdown/documentation/processstep.md +51 -0
  105. wbcore/contrib/workflow/static/workflow/markdown/documentation/scriptstep.md +33 -0
  106. wbcore/contrib/workflow/static/workflow/markdown/documentation/splitstep.md +30 -0
  107. wbcore/contrib/workflow/static/workflow/markdown/documentation/startstep.md +27 -0
  108. wbcore/contrib/workflow/static/workflow/markdown/documentation/transition.md +27 -0
  109. wbcore/contrib/workflow/static/workflow/markdown/documentation/userstep.md +42 -0
  110. wbcore/contrib/workflow/static/workflow/markdown/documentation/workflow.md +32 -0
  111. wbcore/contrib/workflow/templates/Test_Templates.txt +25 -0
  112. wbcore/contrib/workflow/tests/test_models/step/test_decision_step.py +79 -0
  113. wbcore/contrib/workflow/tests/test_models/step/test_email_step.py +45 -0
  114. wbcore/contrib/workflow/tests/test_models/step/test_finish_step.py +105 -0
  115. wbcore/contrib/workflow/tests/test_models/step/test_join_step.py +127 -0
  116. wbcore/contrib/workflow/tests/test_models/step/test_script_step.py +24 -0
  117. wbcore/contrib/workflow/tests/test_models/step/test_split_step.py +49 -0
  118. wbcore/contrib/workflow/tests/test_models/step/test_step.py +621 -0
  119. wbcore/contrib/workflow/tests/test_models/step/test_user_step.py +225 -0
  120. wbcore/contrib/workflow/tests/test_models/test_condition.py +103 -0
  121. wbcore/contrib/workflow/tests/test_models/test_data.py +134 -0
  122. wbcore/contrib/workflow/tests/test_models/test_process.py +98 -0
  123. wbcore/contrib/workflow/tests/test_models/test_transition.py +128 -0
  124. wbcore/contrib/workflow/tests/test_models/test_workflow.py +358 -0
  125. wbcore/locale/de/LC_MESSAGES/django.po +667 -0
  126. wbcore/templates/errors/404.html +134 -0
  127. wbcore/templates/errors/500.html +138 -0
  128. wbcore/templates/errors/503.html +132 -0
  129. wbcore/templates/errors/custom.html +132 -0
  130. wbcore/templates/forms.py +0 -0
  131. wbcore/templates/notifications/email_template.html +43 -0
  132. wbcore/templates/wbcore/admin/change_list.html +8 -0
  133. wbcore/templates/wbcore/admin/csv_form.html +15 -0
  134. wbcore/templates/wbcore/dynamic_color_array.html +29 -0
  135. wbcore/templates/wbcore/email_base_template.html +335 -0
  136. wbcore/templates/wbcore/email_notification_template.html +10 -0
  137. wbcore/templates/wbcore/frontend.html +51 -0
  138. wbcore/test/e2e_helpers_methods/e2e_checks.py +121 -0
  139. wbcore/test/e2e_helpers_methods/e2e_helper_methods.py +395 -0
  140. wbcore/tests/test_permissions/test_backend.py +29 -0
  141. {wbcore-2.2.1.dist-info → wbcore-2.2.4.dist-info}/METADATA +1 -1
  142. {wbcore-2.2.1.dist-info → wbcore-2.2.4.dist-info}/RECORD +143 -3
  143. {wbcore-2.2.1.dist-info → wbcore-2.2.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,225 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+ from rest_framework.reverse import reverse
5
+ from wbcore.contrib.authentication.factories import UserFactory
6
+ from wbcore.contrib.directory.factories import BankingContactFactory, PersonFactory
7
+ from wbcore.contrib.workflow.models import ProcessStep
8
+
9
+
10
+ @pytest.mark.django_db
11
+ class TestUserStep:
12
+ def test_get_assigned_group(self, user_step_factory):
13
+ user_step = user_step_factory()
14
+ assert user_step.get_assigned_group() == user_step.group
15
+
16
+ def test_get_assigned_user(self, user_step_factory):
17
+ user = UserFactory()
18
+ user_step = user_step_factory(assignee=user, group=None)
19
+ assert user_step.get_assigned_user() == user
20
+
21
+ def test_execute_assignee_method(self, process_step_factory, user_step_factory):
22
+ step = user_step_factory()
23
+ manager = PersonFactory()
24
+ manager_account = UserFactory(profile=manager)
25
+ assignee = PersonFactory(relationship_managers=[manager])
26
+ instance = BankingContactFactory(entry=assignee)
27
+ process_step = process_step_factory(step=step, process__instance=instance)
28
+ process_step.step.execute_assignee_method(
29
+ process_step, "manager_of_instance_assignee", assignee_field="entry", assignee_type="entry"
30
+ )
31
+ assert process_step.assignee == manager_account
32
+
33
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
34
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
35
+ def test_run(self, mock_notify, mock_execute, process_step_factory, transition_factory, user_step_factory):
36
+ kwargs = {"test": "Test"}
37
+ step = user_step_factory(notify_user=True, kwargs=kwargs)
38
+ user = UserFactory(groups=[step.group])
39
+ process_step = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step)
40
+ transition_factory(from_step=step)
41
+ step.run(process_step)
42
+ assert mock_notify.call_args.args == ([user], process_step)
43
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
44
+ assert mock_execute.call_args.kwargs == kwargs
45
+
46
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
47
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
48
+ def test_run_no_kwargs(
49
+ self, mock_notify, mock_execute, process_step_factory, transition_factory, user_step_factory
50
+ ):
51
+ step = user_step_factory(notify_user=True)
52
+ user = UserFactory(groups=[step.group])
53
+ process_step = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step)
54
+ transition_factory(from_step=step)
55
+ step.run(process_step)
56
+ assert mock_notify.call_args.args == ([user], process_step)
57
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
58
+ assert mock_execute.call_args.kwargs == {}
59
+
60
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
61
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
62
+ def test_run_no_notification(
63
+ self, mock_notify, mock_execute, process_step_factory, transition_factory, user_step_factory
64
+ ):
65
+ kwargs = {"test": "Test"}
66
+ step = user_step_factory(notify_user=False, kwargs=kwargs)
67
+ UserFactory(groups=[step.group])
68
+ process_step = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step)
69
+ transition_factory(from_step=step)
70
+ step.run(process_step)
71
+ assert not mock_notify.called
72
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
73
+ assert mock_execute.call_args.kwargs == kwargs
74
+
75
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
76
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
77
+ def test_run_assignee_method_failed(
78
+ self, mock_notify, mock_execute, process_step_factory, transition_factory, user_step_factory
79
+ ):
80
+ kwargs = {"test": "Test"}
81
+ step = user_step_factory(notify_user=True, kwargs=kwargs)
82
+ UserFactory(groups=[step.group])
83
+ process_step = process_step_factory(state=ProcessStep.StepState.FAILED, step=step)
84
+ transition_factory(from_step=step)
85
+ step.run(process_step)
86
+ assert not mock_notify.called
87
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
88
+ assert mock_execute.call_args.kwargs == kwargs
89
+
90
+ @patch("wbcore.contrib.workflow.models.step.UserStep.set_failed")
91
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
92
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
93
+ def test_run_no_assignee(
94
+ self, mock_notify, mock_execute, mock_failed, process_step_factory, transition_factory, user_step_factory
95
+ ):
96
+ kwargs = {"test": "Test"}
97
+ step = user_step_factory(notify_user=True, kwargs=kwargs)
98
+ process_step = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step)
99
+ transition_factory(from_step=step)
100
+ step.run(process_step)
101
+ assert not mock_notify.called
102
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
103
+ assert mock_execute.call_args.kwargs == kwargs
104
+ assert mock_failed.call_args.args[0] == process_step
105
+
106
+ @patch("wbcore.contrib.workflow.models.step.UserStep.set_failed")
107
+ @patch("wbcore.contrib.workflow.models.step.UserStep.execute_assignee_method")
108
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
109
+ def test_run_no_transition(
110
+ self, mock_notify, mock_execute, mock_failed, process_step_factory, transition_factory, user_step_factory
111
+ ):
112
+ kwargs = {"test": "Test"}
113
+ step = user_step_factory(notify_user=True, kwargs=kwargs)
114
+ UserFactory(groups=[step.group])
115
+ process_step = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step)
116
+ step.run(process_step)
117
+ assert not mock_notify.called
118
+ assert mock_execute.call_args.args == (process_step, step.assignee_method)
119
+ assert mock_execute.call_args.kwargs == kwargs
120
+ assert mock_failed.call_args.args[0] == process_step
121
+
122
+ @patch("wbcore.contrib.workflow.models.step.process_can_finish.delay")
123
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
124
+ def test_set_failed_user_step_notify_user(
125
+ self, mock_notify, mock_can_finish, process_step_factory, user_step_factory
126
+ ):
127
+ step = user_step_factory(notify_user=True)
128
+ UserFactory(groups=[step.group])
129
+ process_step = process_step_factory(step=step, error_message=None)
130
+ error_message = "Error message"
131
+ step.set_failed(process_step, error_message)
132
+ assert process_step.state == ProcessStep.StepState.FAILED
133
+ assert process_step.error_message == error_message
134
+ assert mock_notify.call_args.args == (process_step.get_all_assignees(), process_step, error_message)
135
+ assert mock_can_finish.call_args.args == (process_step.process.pk,)
136
+
137
+ @patch("wbcore.contrib.workflow.models.step.process_can_finish.delay")
138
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
139
+ def test_set_failed_user_step_not_notify(
140
+ self, mock_notify, mock_can_finish, process_step_factory, user_step_factory
141
+ ):
142
+ step = user_step_factory(notify_user=False)
143
+ UserFactory(groups=[step.group])
144
+ process_step = process_step_factory(step=step, error_message=None)
145
+ error_message = "Error message"
146
+ step.set_failed(process_step, error_message)
147
+ assert process_step.state == ProcessStep.StepState.FAILED
148
+ assert process_step.error_message == error_message
149
+ assert not mock_notify.called
150
+ assert mock_can_finish.call_args.args == (process_step.process.pk,)
151
+
152
+ @patch("wbcore.contrib.workflow.models.step.process_can_finish.delay")
153
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
154
+ def test_set_failed_user_step_no_assignees(
155
+ self, mock_notify, mock_can_finish, process_step_factory, user_step_factory
156
+ ):
157
+ step = user_step_factory(notify_user=True)
158
+ process_step = process_step_factory(step=step, error_message=None)
159
+ error_message = "Error message"
160
+ step.set_failed(process_step, error_message)
161
+ assert process_step.state == ProcessStep.StepState.FAILED
162
+ assert process_step.error_message == error_message
163
+ assert not mock_notify.called
164
+ assert mock_can_finish.call_args.args == (process_step.process.pk,)
165
+
166
+ @patch("wbcore.contrib.workflow.models.step.send_notification")
167
+ def test_notify_single_assignee(self, mock_notification, process_step_factory, user_step_factory):
168
+ step = user_step_factory()
169
+ process_step = process_step_factory(step=step)
170
+ assignee_list = [UserFactory()]
171
+ step.notify_assignees(assignee_list, process_step)
172
+ assert mock_notification.call_args.kwargs == {
173
+ "code": "workflow.userstep.notify_next_step",
174
+ "title": "Workflow Step Awaiting Your Decision",
175
+ "body": "You were assigned to a workflow step. Please select the next step.",
176
+ "user": assignee_list[0],
177
+ "endpoint": reverse(f"{process_step.get_endpoint_basename()}-detail", args=[process_step.id]),
178
+ }
179
+
180
+ @patch("wbcore.contrib.workflow.models.step.send_notification")
181
+ def test_notify_assignee_error(self, mock_notification, process_step_factory, user_step_factory):
182
+ step = user_step_factory()
183
+ process_step = process_step_factory(step=step)
184
+ assignee_list = [UserFactory()]
185
+ error_message = "Test error"
186
+ step.notify_assignees(assignee_list, process_step, error_message)
187
+ assert mock_notification.call_args.kwargs == {
188
+ "code": "workflow.userstep.notify_failed_step",
189
+ "title": "Assigned Workflow Step Failed",
190
+ "body": f"A workflow step you were assigned to just failed with the error message '{error_message}'. Please take appropriate action.",
191
+ "user": assignee_list[0],
192
+ "endpoint": reverse(f"{process_step.get_endpoint_basename()}-detail", args=[process_step.id]),
193
+ }
194
+
195
+ @patch("wbcore.contrib.workflow.models.step.send_notification")
196
+ def test_notify_assignee_list(self, mock_notification, process_step_factory, user_step_factory):
197
+ step = user_step_factory()
198
+ process_step = process_step_factory(step=step)
199
+ assignee_list = UserFactory.create_batch(3)
200
+ step.notify_assignees(assignee_list, process_step)
201
+ assert mock_notification.call_count == 3
202
+
203
+ @patch("wbcore.contrib.workflow.models.step.send_notification")
204
+ def test_notify_assignee_inactive_user(self, mock_notification, process_step_factory, user_step_factory):
205
+ step = user_step_factory()
206
+ process_step = process_step_factory(step=step)
207
+ assignee_list = UserFactory.create_batch(3)
208
+ inactive_user = UserFactory(is_active=False)
209
+ assignee_list.append(inactive_user)
210
+ step.notify_assignees(assignee_list, process_step)
211
+ assert mock_notification.call_count == 3
212
+ for call in mock_notification.call_args_list:
213
+ assert call[1]["user"] != inactive_user
214
+
215
+ @patch("wbcore.contrib.workflow.models.step.send_notification")
216
+ @patch("wbcore.contrib.workflow.models.step.Step.user_can_see_step")
217
+ def test_notify_assignee_user_cant_see(
218
+ self, mock_can_see, mock_notification, process_step_factory, user_step_factory
219
+ ):
220
+ step = user_step_factory()
221
+ process_step = process_step_factory(step=step)
222
+ assignee_list = [UserFactory()]
223
+ mock_can_see.return_value = False
224
+ step.notify_assignees(assignee_list, process_step)
225
+ assert not mock_notification.called
@@ -0,0 +1,103 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+ from wbcore.contrib.directory.factories import PersonFactory
5
+ from wbcore.contrib.workflow.models import Condition
6
+
7
+
8
+ @pytest.mark.django_db
9
+ class TestCondition:
10
+ def test_errors_satisfied_not_called(self, condition_factory):
11
+ condition = condition_factory()
12
+ with pytest.raises(ValueError):
13
+ condition.errors
14
+
15
+ def test_errors(self, condition_factory):
16
+ condition = condition_factory()
17
+ with patch.object(condition, "_errors", create=True):
18
+ assert condition.errors
19
+
20
+ def test_satisfied_attribute_error(self, condition_factory):
21
+ instance = PersonFactory()
22
+ condition = condition_factory(attribute_name="Test")
23
+ assert not condition.satisfied(instance)
24
+ assert len(condition.errors) == 1
25
+
26
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
27
+ def test_satisfied_value_error(self, mock_cast, condition_factory):
28
+ instance = PersonFactory()
29
+ condition = condition_factory()
30
+ mock_cast.side_effect = ValueError
31
+ assert not condition.satisfied(instance)
32
+ assert len(condition.errors) == 1
33
+
34
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
35
+ def test_satisfied_eq(self, mock_cast, condition_factory):
36
+ instance = PersonFactory()
37
+ condition1 = condition_factory(operator=Condition.Operator.EQ, negate_operator=False)
38
+ condition2 = condition_factory(operator=Condition.Operator.EQ, negate_operator=True)
39
+ mock_cast.return_value = instance.first_name
40
+ assert condition1.satisfied(instance)
41
+ assert not condition1.errors
42
+ assert not condition2.satisfied(instance)
43
+ assert not condition2.errors
44
+
45
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
46
+ def test_satisfied_gt(self, mock_cast, condition_factory):
47
+ instance = PersonFactory(personality_profile_red=5)
48
+ condition1 = condition_factory(
49
+ attribute_name="personality_profile_red", operator=Condition.Operator.GT, negate_operator=False
50
+ )
51
+ condition2 = condition_factory(
52
+ attribute_name="personality_profile_red", operator=Condition.Operator.GT, negate_operator=True
53
+ )
54
+ mock_cast.return_value = 3
55
+ assert condition1.satisfied(instance)
56
+ assert not condition1.errors
57
+ assert not condition2.satisfied(instance)
58
+ assert not condition2.errors
59
+
60
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
61
+ def test_satisfied_gte(self, mock_cast, condition_factory):
62
+ instance = PersonFactory(personality_profile_red=5)
63
+ condition1 = condition_factory(
64
+ attribute_name="personality_profile_red", operator=Condition.Operator.GTE, negate_operator=False
65
+ )
66
+ condition2 = condition_factory(
67
+ attribute_name="personality_profile_red", operator=Condition.Operator.GTE, negate_operator=True
68
+ )
69
+ mock_cast.return_value = 5
70
+ assert condition1.satisfied(instance)
71
+ assert not condition1.errors
72
+ assert not condition2.satisfied(instance)
73
+ assert not condition2.errors
74
+
75
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
76
+ def test_satisfied_lt(self, mock_cast, condition_factory):
77
+ instance = PersonFactory(personality_profile_red=2)
78
+ condition1 = condition_factory(
79
+ attribute_name="personality_profile_red", operator=Condition.Operator.LT, negate_operator=False
80
+ )
81
+ condition2 = condition_factory(
82
+ attribute_name="personality_profile_red", operator=Condition.Operator.LT, negate_operator=True
83
+ )
84
+ mock_cast.return_value = 5
85
+ assert condition1.satisfied(instance)
86
+ assert not condition1.errors
87
+ assert not condition2.satisfied(instance)
88
+ assert not condition2.errors
89
+
90
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_from_target_object")
91
+ def test_satisfied_lte(self, mock_cast, condition_factory):
92
+ instance = PersonFactory(personality_profile_red=2)
93
+ condition1 = condition_factory(
94
+ attribute_name="personality_profile_red", operator=Condition.Operator.LTE, negate_operator=False
95
+ )
96
+ condition2 = condition_factory(
97
+ attribute_name="personality_profile_red", operator=Condition.Operator.LTE, negate_operator=True
98
+ )
99
+ mock_cast.return_value = 2
100
+ assert condition1.satisfied(instance)
101
+ assert not condition1.errors
102
+ assert not condition2.satisfied(instance)
103
+ assert not condition2.errors
@@ -0,0 +1,134 @@
1
+ from datetime import date, datetime
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+ from wbcore.contrib.workflow.models import Data
6
+
7
+
8
+ @pytest.mark.django_db
9
+ class TestData:
10
+ @pytest.mark.parametrize(
11
+ ("type", "field_name"),
12
+ [
13
+ (Data.DataType.CHAR, "CharField"),
14
+ (Data.DataType.BOOL, "BooleanField"),
15
+ (Data.DataType.DATE, "DateField"),
16
+ (Data.DataType.DATETIME, "DateTimeField"),
17
+ (Data.DataType.INT, "IntegerField"),
18
+ ],
19
+ )
20
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_to_datatype")
21
+ def test_get_serializer_field(self, mock_cast, data_factory, type, field_name):
22
+ data = data_factory(help_text=None, data_type=type)
23
+ field = data.get_serializer_field()
24
+ assert field.__class__.__name__ == field_name
25
+ assert field.label == data.label
26
+ assert field.required == data.required
27
+ assert "default" not in field._kwargs
28
+ assert "help_text" not in field._kwargs
29
+ assert not mock_cast.called
30
+
31
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_to_datatype")
32
+ def test_get_serializer_field_help_text(self, mock_cast, data_factory):
33
+ data = data_factory()
34
+ field = data.get_serializer_field()
35
+ assert field.label == data.label
36
+ assert field.required == data.required
37
+ assert "default" not in field._kwargs
38
+ assert field.help_text == data.help_text
39
+ assert not mock_cast.called
40
+
41
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_to_datatype")
42
+ def test_get_serializer_field_default(self, mock_cast, data_factory):
43
+ data_type = Data.DataType.INT
44
+ default_value = "50"
45
+ casted_default_value = 50
46
+ data = data_factory(default=default_value, data_type=data_type)
47
+ mock_cast.return_value = casted_default_value
48
+ field = data.get_serializer_field()
49
+ assert mock_cast.call_args.args == (data_type, default_value)
50
+ assert field.label == data.label
51
+ assert field.required == data.required
52
+ assert field.default == casted_default_value
53
+ assert field.help_text == data.help_text
54
+
55
+ @pytest.mark.parametrize(
56
+ ("data_type", "value", "expected"),
57
+ [
58
+ (Data.DataType.BOOL, "True", True),
59
+ (Data.DataType.BOOL, "true", True),
60
+ (Data.DataType.BOOL, "False", False),
61
+ (Data.DataType.BOOL, "false", False),
62
+ (Data.DataType.DATE, "12.07.1054", date(1054, 7, 12)),
63
+ (Data.DataType.DATETIME, "12.07.1054 13:47:09", datetime(1054, 7, 12, 13, 47, 9)),
64
+ (Data.DataType.CHAR, "123456", "123456"),
65
+ (Data.DataType.INT, "123456", 123456),
66
+ ],
67
+ )
68
+ def test_cast_value_to_datatype(self, data_type, value, expected):
69
+ assert Data.cast_value_to_datatype(data_type, value) == expected
70
+
71
+ @pytest.mark.parametrize(
72
+ ("data_type", "value"),
73
+ [
74
+ (Data.DataType.BOOL, "Test"),
75
+ (Data.DataType.BOOL, "1"),
76
+ (Data.DataType.BOOL, "0"),
77
+ (Data.DataType.DATE, "07/12/1054"),
78
+ (Data.DataType.DATETIME, "07/12/1054 13:47:09"),
79
+ (Data.DataType.INT, "Test"),
80
+ ],
81
+ )
82
+ def test_cast_value_to_datatype_error(self, data_type, value):
83
+ with pytest.raises(ValueError):
84
+ Data.cast_value_to_datatype(data_type, value)
85
+
86
+ @pytest.mark.parametrize(
87
+ ("target", "data_type"),
88
+ [
89
+ (datetime(2003, 8, 28, 7, 18, 4), Data.DataType.DATETIME),
90
+ (date(2003, 8, 28), Data.DataType.DATE),
91
+ (True, Data.DataType.BOOL),
92
+ (False, Data.DataType.BOOL),
93
+ (69, Data.DataType.INT),
94
+ ("Test", Data.DataType.CHAR),
95
+ ],
96
+ )
97
+ @patch("wbcore.contrib.workflow.models.data.Data.cast_value_to_datatype")
98
+ def test_cast_value_from_target_object(self, mock_cast, target, data_type):
99
+ Data.cast_value_from_target_object(target, "Test")
100
+ assert mock_cast.call_args.args == (data_type, "Test")
101
+
102
+ @pytest.mark.parametrize(
103
+ "target",
104
+ [None, Data, str, {}, []],
105
+ )
106
+ def test_cast_value_from_target_object_error(self, target):
107
+ with pytest.raises(ValueError):
108
+ Data.cast_value_from_target_object(target, "Test")
109
+
110
+ @pytest.mark.parametrize(
111
+ ("data_object", "data_type", "expected"),
112
+ [
113
+ (datetime(2003, 8, 28, 7, 18, 4), Data.DataType.DATETIME, "28.08.2003 07:18:04"),
114
+ (date(2003, 8, 28), Data.DataType.DATE, "28.08.2003"),
115
+ (True, Data.DataType.BOOL, "True"),
116
+ (False, Data.DataType.BOOL, "False"),
117
+ (69, Data.DataType.INT, "69"),
118
+ ("Test", Data.DataType.CHAR, "Test"),
119
+ ],
120
+ )
121
+ def test_cast_datatype_to_string(self, data_type, data_object, expected):
122
+ assert Data.cast_datatype_to_string(data_type, data_object) == expected
123
+
124
+ @pytest.mark.parametrize(
125
+ ("data_object", "data_type"),
126
+ [
127
+ (69, Data.DataType.DATETIME),
128
+ ("Test", Data.DataType.DATE),
129
+ (datetime(2003, 8, 28, 7, 18, 4), Data.DataType.BOOL),
130
+ ],
131
+ )
132
+ def test_cast_datatype_to_string_error(self, data_type, data_object):
133
+ with pytest.raises(ValueError):
134
+ Data.cast_datatype_to_string(data_type, data_object)
@@ -0,0 +1,98 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+ from wbcore.contrib.authentication.factories import GroupFactory, UserFactory
5
+ from wbcore.contrib.directory.factories import PersonFactory
6
+ from wbcore.contrib.workflow.factories import UserStepFactory
7
+ from wbcore.contrib.workflow.models import Process, ProcessStep
8
+
9
+
10
+ @pytest.mark.django_db
11
+ class TestProcess:
12
+ @patch("wbcore.contrib.workflow.models.process.ProcessStep.get_all_assignees")
13
+ @patch("wbcore.contrib.workflow.models.step.UserStep.notify_assignees")
14
+ def test_set_failed(
15
+ self,
16
+ mock_notify,
17
+ mock_assignees,
18
+ process_step_factory,
19
+ process_factory,
20
+ random_child_step_factory,
21
+ user_step_factory,
22
+ ):
23
+ step = random_child_step_factory(exclude_factories=[UserStepFactory])
24
+ user_step_no_notify = user_step_factory(notify_user=False)
25
+ user_step_notify = user_step_factory(notify_user=True)
26
+ process = process_factory(state=Process.ProcessState.ACTIVE)
27
+ process_step1 = process_step_factory(
28
+ state=ProcessStep.StepState.ACTIVE, process=process, step=step, error_message=None
29
+ )
30
+ process_step2 = process_step_factory(
31
+ state=ProcessStep.StepState.WAITING, process=process, step=step, error_message=None
32
+ )
33
+ process_step3 = process_step_factory(
34
+ state=ProcessStep.StepState.CANCELED, process=process, step=step, error_message=None
35
+ )
36
+ process_step4 = process_step_factory(
37
+ state=ProcessStep.StepState.FINISHED, process=process, step=step, error_message=None
38
+ )
39
+ process_step5 = process_step_factory(state=ProcessStep.StepState.ACTIVE, step=step, error_message=None)
40
+ process_step6 = process_step_factory(
41
+ state=ProcessStep.StepState.ACTIVE, process=process, step=user_step_no_notify, error_message=None
42
+ )
43
+ process_step7 = process_step_factory(
44
+ state=ProcessStep.StepState.ACTIVE, process=process, step=user_step_notify, error_message=None
45
+ )
46
+ user = UserFactory()
47
+ mock_assignees.return_value = [user]
48
+ process.set_failed()
49
+ assert mock_notify.call_count == 1
50
+ assert mock_notify.call_args.args[0] == [user]
51
+ assert str(mock_notify.call_args.args[1].pk) == process_step7.pk
52
+ assert mock_assignees.call_count == 1
53
+ for process_step in ProcessStep.objects.filter(
54
+ id__in=[process_step1.pk, process_step2.pk, process_step6.pk, process_step7.pk]
55
+ ):
56
+ assert process_step.state == ProcessStep.StepState.FAILED
57
+ assert process_step.error_message
58
+ for process_step in ProcessStep.objects.filter(id__in=[process_step3.pk, process_step4.pk, process_step5.pk]):
59
+ assert process_step.state != ProcessStep.StepState.FAILED
60
+ assert process_step.error_message is None
61
+ assert Process.objects.get(id=process.pk).state == Process.ProcessState.FAILED
62
+
63
+
64
+ @pytest.mark.django_db
65
+ class TestProcessStep:
66
+ def test_get_instance(self, process_step_factory):
67
+ attached_instance = PersonFactory()
68
+ process_step = process_step_factory(process__instance=attached_instance)
69
+ assert process_step.get_instance() == attached_instance
70
+
71
+ def test_get_instance_no_attached(self, process_step_factory):
72
+ process_step = process_step_factory(process__instance=None, process__instance_id=None)
73
+ assert process_step.get_instance() is None
74
+
75
+ def test_get_all_assignees_assignee(self, process_step_factory):
76
+ user = UserFactory()
77
+ group = GroupFactory()
78
+ process_step = process_step_factory(assignee=user, group=group)
79
+ assert process_step.get_all_assignees() == [user]
80
+
81
+ def test_get_all_assignees_group(self, process_step_factory):
82
+ group = GroupFactory()
83
+ user1 = UserFactory(groups=[group])
84
+ user2 = UserFactory(groups=[group])
85
+ UserFactory()
86
+ process_step = process_step_factory(group=group, assignee=None)
87
+ assert set(process_step.get_all_assignees()) == {user1, user2}
88
+
89
+ def test_get_all_assignees_empty_group(self, process_step_factory):
90
+ group = GroupFactory()
91
+ process_step = process_step_factory(group=group, assignee=None)
92
+ assert process_step.get_all_assignees() == []
93
+
94
+ def test_get_all_assignees_none(self, process_step_factory):
95
+ group = GroupFactory()
96
+ UserFactory(groups=[group])
97
+ process_step = process_step_factory(group=None, assignee=None)
98
+ assert process_step.get_all_assignees() == []