wbcore 1.46.0__py2.py3-none-any.whl → 1.58.2__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.
- wbcore/cache/decorators.py +5 -3
- wbcore/cache/registry.py +14 -7
- wbcore/configs/__init__.py +1 -0
- wbcore/configs/configs.py +5 -0
- wbcore/configs/decorators.py +1 -1
- wbcore/configurations/configurations/apps.py +3 -2
- wbcore/configurations/configurations/authentication.py +1 -1
- wbcore/configurations/configurations/base.py +1 -1
- wbcore/configurations/configurations/cache.py +1 -1
- wbcore/configurations/configurations/i18nl10n.py +2 -1
- wbcore/configurations/configurations/maintenance.py +1 -1
- wbcore/configurations/configurations/media.py +1 -1
- wbcore/configurations/configurations/middleware.py +1 -1
- wbcore/configurations/configurations/rest_framework.py +1 -1
- wbcore/configurations/configurations/static.py +3 -3
- wbcore/configurations/configurations/wbcore.py +1 -1
- wbcore/content_type/serializers.py +13 -5
- wbcore/content_type/utils.py +3 -3
- wbcore/content_type/viewsets.py +2 -2
- wbcore/contrib/agenda/filters/calendar_item.py +5 -4
- wbcore/contrib/agenda/locale/de/LC_MESSAGES/django.po +145 -52
- wbcore/contrib/agenda/locale/de/LC_MESSAGES/django.po.translated +236 -0
- wbcore/contrib/agenda/locale/en/LC_MESSAGES/django.po +200 -0
- wbcore/contrib/agenda/locale/fr/LC_MESSAGES/django.po +201 -0
- wbcore/contrib/agenda/viewsets/calendar_items.py +7 -7
- wbcore/contrib/agenda/viewsets/menu/calendar_items.py +0 -6
- wbcore/contrib/ai/exceptions.py +5 -5
- wbcore/contrib/ai/llm/config.py +76 -27
- wbcore/contrib/ai/llm/mixins.py +5 -8
- wbcore/contrib/ai/llm/utils.py +50 -26
- wbcore/contrib/authentication/admin.py +2 -2
- wbcore/contrib/authentication/factories/__init__.py +8 -1
- wbcore/contrib/authentication/factories/users.py +19 -0
- wbcore/contrib/authentication/filters.py +1 -2
- wbcore/contrib/authentication/locale/de/LC_MESSAGES/django.po +209 -187
- wbcore/contrib/authentication/locale/de/LC_MESSAGES/django.po.translated +634 -0
- wbcore/contrib/authentication/locale/en/LC_MESSAGES/django.po +590 -0
- wbcore/contrib/authentication/locale/fr/LC_MESSAGES/django.po +592 -0
- wbcore/contrib/authentication/models/users.py +3 -3
- wbcore/contrib/authentication/models/users_activities.py +1 -1
- wbcore/contrib/authentication/serializers/users.py +2 -2
- wbcore/contrib/authentication/tests/test_tokens.py +3 -3
- wbcore/contrib/authentication/tests/test_users.py +0 -1
- wbcore/contrib/authentication/urls.py +0 -4
- wbcore/contrib/authentication/viewsets/endpoints/user_activities.py +2 -11
- wbcore/contrib/authentication/viewsets/endpoints/users.py +0 -3
- wbcore/contrib/authentication/viewsets/user_activities.py +2 -1
- wbcore/contrib/authentication/viewsets/users.py +6 -4
- wbcore/contrib/color/models.py +2 -1
- wbcore/contrib/currency/factories.py +1 -1
- wbcore/contrib/currency/import_export/backends/fixerio/currency_fx_rates.py +3 -1
- wbcore/contrib/currency/models.py +30 -8
- wbcore/contrib/currency/serializers.py +5 -1
- wbcore/contrib/currency/tests/test_serializers.py +7 -3
- wbcore/contrib/currency/tests/test_viewsets.py +1 -1
- wbcore/contrib/currency/viewsets/currency.py +2 -2
- wbcore/contrib/currency/viewsets/endpoints/currency_fx_rates.py +0 -9
- wbcore/contrib/dataloader/tests/test/dataloaders/protocols.py +1 -2
- wbcore/contrib/dataloader/utils.py +2 -2
- wbcore/contrib/directory/factories/__init__.py +1 -1
- wbcore/contrib/directory/factories/entries.py +2 -1
- wbcore/contrib/directory/filters/entries.py +9 -0
- wbcore/contrib/directory/locale/de/LC_MESSAGES/django.po +728 -714
- wbcore/contrib/directory/locale/de/LC_MESSAGES/django.po.translated +1779 -0
- wbcore/contrib/directory/locale/en/LC_MESSAGES/django.po +1652 -0
- wbcore/contrib/directory/locale/fr/LC_MESSAGES/django.po +1654 -0
- wbcore/contrib/directory/migrations/0011_person_description_person_i18n.py +24 -0
- wbcore/contrib/directory/migrations/0012_alter_person_managers.py +20 -0
- wbcore/contrib/directory/migrations/0013_alter_clientmanagerrelationship_options.py +17 -0
- wbcore/contrib/directory/models/contacts.py +2 -2
- wbcore/contrib/directory/models/entries.py +31 -5
- wbcore/contrib/directory/models/relationships.py +31 -35
- wbcore/contrib/directory/permissions.py +6 -0
- wbcore/contrib/directory/serializers/companies.py +16 -8
- wbcore/contrib/directory/serializers/contacts.py +8 -8
- wbcore/contrib/directory/serializers/entries.py +26 -15
- wbcore/contrib/directory/serializers/entry_representations.py +4 -2
- wbcore/contrib/directory/serializers/persons.py +12 -10
- wbcore/contrib/directory/serializers/relationships.py +2 -2
- wbcore/contrib/directory/tests/conftest.py +2 -0
- wbcore/contrib/directory/tests/disable_signals.py +11 -1
- wbcore/contrib/directory/tests/signals.py +2 -2
- wbcore/contrib/directory/tests/test_models.py +88 -66
- wbcore/contrib/directory/tests/test_serializers.py +1 -1
- wbcore/contrib/directory/tests/test_viewsets.py +8 -8
- wbcore/contrib/directory/viewsets/buttons/__init__.py +1 -1
- wbcore/contrib/directory/viewsets/buttons/relationships.py +32 -0
- wbcore/contrib/directory/viewsets/contacts.py +6 -6
- wbcore/contrib/directory/viewsets/display/__init__.py +1 -1
- wbcore/contrib/directory/viewsets/display/contacts.py +1 -14
- wbcore/contrib/directory/viewsets/display/entries.py +68 -38
- wbcore/contrib/directory/viewsets/display/relationships.py +26 -50
- wbcore/contrib/directory/viewsets/endpoints/relationships.py +1 -26
- wbcore/contrib/directory/viewsets/entries.py +8 -6
- wbcore/contrib/directory/viewsets/previews/entries.py +3 -3
- wbcore/contrib/directory/viewsets/relationships.py +16 -2
- wbcore/contrib/directory/viewsets/titles/relationships.py +2 -3
- wbcore/contrib/documents/filters.py +0 -2
- wbcore/contrib/documents/locale/de/LC_MESSAGES/django.po +103 -94
- wbcore/contrib/documents/locale/de/LC_MESSAGES/django.po.translated +285 -0
- wbcore/contrib/documents/locale/en/LC_MESSAGES/django.po +271 -0
- wbcore/contrib/documents/locale/fr/LC_MESSAGES/django.po +270 -0
- wbcore/contrib/documents/tests/test_models.py +32 -28
- wbcore/contrib/documents/viewsets/endpoints/shareable_links.py +2 -21
- wbcore/contrib/dynamic_preferences/types.py +108 -0
- wbcore/contrib/dynamic_preferences/viewsets.py +27 -0
- wbcore/contrib/example_app/filters/event.py +3 -1
- wbcore/contrib/example_app/filters/match.py +1 -1
- wbcore/contrib/example_app/models.py +91 -22
- wbcore/contrib/example_app/serializers/person_team.py +4 -4
- wbcore/contrib/example_app/templates/example_app/embedded_view.html +19 -0
- wbcore/contrib/example_app/tests/e2e/test_teams.py +1 -1
- wbcore/contrib/example_app/tests/test_models/test_match.py +17 -7
- wbcore/contrib/example_app/urls.py +2 -0
- wbcore/contrib/example_app/views.py +7 -0
- wbcore/contrib/example_app/viewsets/displays/team.py +23 -4
- wbcore/contrib/example_app/viewsets/menu/menus.py +1 -1
- wbcore/contrib/example_app/viewsets/menus.py +1 -1
- wbcore/contrib/geography/tests/conftest.py +14 -0
- wbcore/contrib/geography/tests/test_models.py +23 -8
- wbcore/contrib/geography/tests/test_viewsets.py +96 -2
- wbcore/contrib/guardian/tests/test_model_mixins.py +3 -4
- wbcore/contrib/guardian/tests/test_tasks.py +9 -9
- wbcore/contrib/guardian/tests/test_viewsets.py +2 -2
- wbcore/contrib/guardian/viewsets/configs/__init__.py +1 -1
- wbcore/contrib/guardian/viewsets/configs/buttons.py +9 -0
- wbcore/contrib/guardian/viewsets/configs/endpoints.py +7 -0
- wbcore/contrib/guardian/viewsets/viewsets.py +2 -0
- wbcore/contrib/i18n/__init__.py +2 -0
- wbcore/contrib/i18n/buttons.py +33 -0
- wbcore/contrib/i18n/serializers/__init__.py +0 -0
- wbcore/contrib/i18n/serializers/fields.py +20 -0
- wbcore/contrib/i18n/serializers/mixins.py +13 -0
- wbcore/contrib/i18n/tests/conftest.py +11 -0
- wbcore/contrib/i18n/tests/test_viewsets.py +67 -0
- wbcore/contrib/i18n/translation.py +140 -0
- wbcore/contrib/i18n/viewsets.py +36 -0
- wbcore/contrib/icons/backends/default.py +1 -0
- wbcore/contrib/icons/backends/material.py +1 -0
- wbcore/contrib/icons/icons.py +5 -8
- wbcore/contrib/io/admin.py +1 -0
- wbcore/contrib/io/backends/mail.py +3 -2
- wbcore/contrib/io/backends/utils.py +14 -17
- wbcore/contrib/io/exceptions.py +8 -0
- wbcore/contrib/io/factories.py +1 -1
- wbcore/contrib/io/import_export/backends/mail.py +1 -0
- wbcore/contrib/io/import_export/backends/sftp.py +29 -20
- wbcore/contrib/io/import_export/backends/stream.py +2 -2
- wbcore/contrib/io/import_export/parsers/__init__.py +0 -0
- wbcore/contrib/io/import_export/parsers/base_csv.py +36 -0
- wbcore/contrib/io/import_export/parsers/resources.py +50 -0
- wbcore/contrib/io/imports.py +33 -25
- wbcore/contrib/io/locale/de/LC_MESSAGES/django.po +114 -22
- wbcore/contrib/io/locale/de/LC_MESSAGES/django.po.translated +103 -0
- wbcore/contrib/io/locale/en/LC_MESSAGES/django.po +138 -0
- wbcore/contrib/io/locale/fr/LC_MESSAGES/django.po +138 -0
- wbcore/contrib/io/migrations/0008_importsource_resource_kwargs.py +18 -0
- wbcore/contrib/io/models.py +65 -45
- wbcore/contrib/io/resources.py +0 -6
- wbcore/contrib/io/serializers.py +2 -2
- wbcore/contrib/io/signals.py +4 -0
- wbcore/contrib/io/tests/test_backends.py +19 -13
- wbcore/contrib/io/tests/test_exports.py +1 -1
- wbcore/contrib/io/tests/test_imports.py +1 -1
- wbcore/contrib/io/tests/test_models.py +47 -14
- wbcore/contrib/io/tests/test_viewsets.py +271 -0
- wbcore/contrib/io/viewset_mixins.py +41 -54
- wbcore/contrib/notifications/admin.py +1 -0
- wbcore/contrib/notifications/apps.py +2 -1
- wbcore/contrib/notifications/backends/abstract_backend.py +2 -4
- wbcore/contrib/notifications/backends/firebase/backends.py +5 -2
- wbcore/contrib/notifications/dispatch.py +18 -7
- wbcore/contrib/notifications/factories/notification_types.py +1 -0
- wbcore/contrib/notifications/locale/de/LC_MESSAGES/django.po +25 -19
- wbcore/contrib/notifications/locale/de/LC_MESSAGES/django.po.translated +63 -0
- wbcore/contrib/notifications/locale/en/LC_MESSAGES/django.po +61 -0
- wbcore/contrib/notifications/locale/fr/LC_MESSAGES/django.po +62 -0
- wbcore/contrib/notifications/migrations/0008_notificationtype_is_lock.py +18 -0
- wbcore/contrib/notifications/migrations/0009_alter_notificationtypesetting_options_and_more.py +32 -0
- wbcore/contrib/notifications/models/notification_types.py +67 -24
- wbcore/contrib/notifications/serializers/notification_types.py +16 -1
- wbcore/contrib/notifications/tests/test_models/test_tokens.py +8 -0
- wbcore/contrib/notifications/tests/test_serializers/test_notification_types.py +5 -0
- wbcore/contrib/notifications/tests/test_viewsets/test_notification_types.py +3 -5
- wbcore/contrib/notifications/utils.py +3 -2
- wbcore/contrib/notifications/viewsets/configs/notification_types.py +28 -6
- wbcore/contrib/notifications/viewsets/menus.py +1 -1
- wbcore/contrib/notifications/viewsets/notification_types.py +12 -2
- wbcore/contrib/pandas/fields.py +38 -10
- wbcore/contrib/pandas/filters.py +4 -1
- wbcore/contrib/pandas/filterset.py +8 -7
- wbcore/contrib/pandas/tests/test_fields/test_number_fields.py +2 -7
- wbcore/contrib/pandas/utils.py +1 -1
- wbcore/contrib/pandas/views.py +14 -13
- wbcore/contrib/tags/models/tags.py +4 -1
- wbcore/contrib/workflow/factories/display.py +2 -2
- wbcore/contrib/workflow/factories/transition.py +16 -15
- wbcore/contrib/workflow/locale/de/LC_MESSAGES/django.po +457 -566
- wbcore/contrib/workflow/locale/de/LC_MESSAGES/django.po.translated +1326 -0
- wbcore/contrib/workflow/locale/en/LC_MESSAGES/django.po +1102 -0
- wbcore/contrib/workflow/locale/fr/LC_MESSAGES/django.po +1114 -0
- wbcore/contrib/workflow/models/data.py +7 -4
- wbcore/contrib/workflow/models/process.py +2 -2
- wbcore/contrib/workflow/models/step.py +57 -15
- wbcore/contrib/workflow/serializers/data.py +8 -8
- wbcore/contrib/workflow/serializers/process.py +3 -2
- wbcore/contrib/workflow/tests/conftest.py +224 -0
- wbcore/contrib/workflow/tests/test_dispatch.py +82 -77
- wbcore/contrib/workflow/tests/test_displays.py +10 -88
- wbcore/contrib/workflow/tests/test_filters.py +57 -40
- wbcore/contrib/workflow/tests/test_models/step/test_decision_step.py +71 -68
- wbcore/contrib/workflow/tests/test_models/step/test_email_step.py +78 -38
- wbcore/contrib/workflow/tests/test_models/step/test_finish_step.py +152 -90
- wbcore/contrib/workflow/tests/test_models/step/test_join_step.py +100 -110
- wbcore/contrib/workflow/tests/test_models/step/test_step.py +168 -33
- wbcore/contrib/workflow/tests/test_models/test_condition.py +1 -1
- wbcore/contrib/workflow/tests/test_models/test_workflow.py +3 -3
- wbcore/contrib/workflow/tests/test_serializers.py +172 -150
- wbcore/contrib/workflow/tests/test_viewsets.py +264 -323
- wbcore/contrib/workflow/tests/test_workflow_assignees.py +215 -205
- wbcore/contrib/workflow/viewsets/process.py +4 -1
- wbcore/contrib/workflow/workflows/assignees.py +12 -7
- wbcore/dynamic_preferences_registry.py +102 -0
- wbcore/enums.py +2 -51
- wbcore/filters/fields/choices.py +4 -6
- wbcore/filters/fields/content_type.py +15 -4
- wbcore/filters/fields/datetime.py +50 -25
- wbcore/filters/fields/models.py +18 -9
- wbcore/filters/fields/numbers.py +9 -8
- wbcore/filters/filterset.py +27 -6
- wbcore/filters/mixins.py +41 -42
- wbcore/forms.py +6 -6
- wbcore/fsm/markdown_extensions.py +1 -1
- wbcore/fsm/mixins.py +20 -6
- wbcore/locale/de/LC_MESSAGES/django.po +982 -397
- wbcore/locale/de/LC_MESSAGES/django.po.translated +1580 -0
- wbcore/locale/en/LC_MESSAGES/django.po +1234 -0
- wbcore/locale/fr/LC_MESSAGES/django.po +1235 -0
- wbcore/markdown/models.py +8 -5
- wbcore/markdown/views.py +1 -1
- wbcore/menus/menus.py +2 -2
- wbcore/metadata/configs/buttons/bases.py +10 -7
- wbcore/metadata/configs/buttons/buttons.py +2 -1
- wbcore/metadata/configs/buttons/enums.py +50 -0
- wbcore/metadata/configs/buttons/view_config.py +13 -46
- wbcore/metadata/configs/display/display.py +2 -2
- wbcore/metadata/configs/display/formatting.py +6 -9
- wbcore/metadata/configs/display/instance_display/display.py +5 -2
- wbcore/metadata/configs/display/instance_display/pages.py +1 -1
- wbcore/metadata/configs/display/instance_display/shortcuts.py +1 -1
- wbcore/metadata/configs/display/list_display.py +54 -40
- wbcore/metadata/configs/display/models.py +6 -0
- wbcore/metadata/configs/display/view_config.py +11 -9
- wbcore/metadata/configs/endpoints.py +11 -4
- wbcore/metadata/configs/fields.py +6 -1
- wbcore/metadata/configs/filter_fields.py +12 -13
- wbcore/metadata/configs/identifiers.py +3 -1
- wbcore/metadata/tests/test_buttons.py +13 -16
- wbcore/models/fields.py +2 -2
- wbcore/pagination.py +1 -2
- wbcore/permissions/permissions.py +2 -2
- wbcore/permissions/utils.py +2 -2
- wbcore/release_notes/display.py +2 -8
- wbcore/release_notes/serializers.py +2 -9
- wbcore/release_notes/viewsets.py +8 -2
- wbcore/reversion/viewsets/titles.py +4 -3
- wbcore/serializers/__init__.py +2 -0
- wbcore/serializers/fields/__init__.py +2 -1
- wbcore/serializers/fields/boolean.py +1 -1
- wbcore/serializers/fields/choice.py +28 -4
- wbcore/serializers/fields/datetime.py +45 -36
- wbcore/serializers/fields/fields.py +1 -1
- wbcore/serializers/fields/fsm.py +1 -1
- wbcore/serializers/fields/list.py +2 -5
- wbcore/serializers/fields/mixins.py +24 -11
- wbcore/serializers/fields/number.py +6 -23
- wbcore/serializers/fields/other.py +2 -10
- wbcore/serializers/fields/related.py +4 -6
- wbcore/serializers/fields/text.py +1 -1
- wbcore/serializers/fields/types.py +2 -0
- wbcore/serializers/serializers.py +12 -3
- wbcore/signals/__init__.py +1 -0
- wbcore/signals/clone.py +4 -0
- wbcore/signals/models.py +2 -6
- wbcore/tasks.py +2 -2
- wbcore/templates/wbcore/email_base_template.html +3 -3
- wbcore/test/e2e_helpers_methods/e2e_checks.py +10 -4
- wbcore/test/e2e_helpers_methods/e2e_helper_methods.py +4 -2
- wbcore/test/mixins.py +52 -102
- wbcore/test/tests.py +6 -9
- wbcore/test/utils.py +3 -4
- wbcore/tests/e2e/test_e2e.py +2 -2
- wbcore/tests/test_cache/test_decorators.py +4 -7
- wbcore/tests/test_configs.py +2 -5
- wbcore/tests/test_enums.py +2 -1
- wbcore/tests/test_fields/test_choice_fields.py +9 -1
- wbcore/tests/test_fields/test_number_fields.py +7 -15
- wbcore/tests/test_fields/test_other_fields.py +1 -2
- wbcore/tests/test_filters/test_mixins.py +35 -35
- wbcore/tests/test_list_display.py +0 -2
- wbcore/tests/test_models/test_mixins.py +1 -1
- wbcore/tests/test_utils/test_date.py +1 -1
- wbcore/tests/test_utils/test_date_builder.py +25 -1
- wbcore/tests/test_utils/test_primary.py +1 -1
- wbcore/urls.py +4 -0
- wbcore/utils/date.py +18 -2
- wbcore/utils/figures.py +2 -2
- wbcore/utils/models.py +21 -4
- wbcore/utils/reportlab.py +7 -0
- wbcore/utils/rrules.py +3 -1
- wbcore/utils/string_loader.py +1 -1
- wbcore/utils/strings.py +3 -3
- wbcore/utils/views.py +8 -3
- wbcore/viewsets/mixins.py +9 -4
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/METADATA +9 -5
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/RECORD +317 -271
- wbcore/contrib/geography/tests/test_serializers.py +0 -7
- wbcore/contrib/geography/tests/tests.py +0 -13
- wbcore/contrib/io/tests/tests.py +0 -19
- wbcore/contrib/workflow/tests/tests.py +0 -25
- {wbcore-1.46.0.dist-info → wbcore-1.58.2.dist-info}/WHEEL +0 -0
|
@@ -1,89 +1,94 @@
|
|
|
1
|
-
from unittest.mock import patch
|
|
2
|
-
|
|
3
1
|
import pytest
|
|
2
|
+
from pytest_mock import MockerFixture
|
|
4
3
|
|
|
5
|
-
from wbcore.contrib.directory.factories import PersonFactory
|
|
6
4
|
from wbcore.contrib.workflow.dispatch import check_workflow_for_instance
|
|
7
|
-
from wbcore.contrib.workflow.
|
|
8
|
-
from wbcore.contrib.workflow.models import Process, ProcessStep
|
|
5
|
+
from wbcore.contrib.workflow.models import Process, ProcessStep, Step, Workflow
|
|
9
6
|
|
|
10
7
|
|
|
11
|
-
@pytest.mark.django_db
|
|
12
8
|
class TestDispatch:
|
|
13
|
-
@
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def mocked_instance(self, mocker: MockerFixture):
|
|
11
|
+
return mocker.MagicMock()
|
|
12
|
+
|
|
13
|
+
# Fixture that automatically patches ContentType lookup in every test.
|
|
14
|
+
@pytest.fixture(autouse=True)
|
|
15
|
+
def patch_content_type(self, mocker: MockerFixture):
|
|
16
|
+
return mocker.patch(
|
|
17
|
+
"wbcore.contrib.workflow.dispatch.ContentType.objects.get_for_model",
|
|
18
|
+
return_value="dummy_content_type",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Fixture for creating a fake process step with a mismatching status.
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def mocked_process_step(self, mocker: MockerFixture):
|
|
24
|
+
# Create the fake casted step.
|
|
25
|
+
mocked_casted_step = mocker.MagicMock(spec=Step)
|
|
26
|
+
|
|
27
|
+
# Create a fake workflow with a status field.
|
|
28
|
+
mocked_workflow = mocker.MagicMock(spec=Workflow)
|
|
29
|
+
mocked_workflow.status_field = "status_a"
|
|
30
|
+
|
|
31
|
+
# Create a fake process that uses the workflow.
|
|
32
|
+
mocked_process = mocker.MagicMock(spec=Process)
|
|
33
|
+
mocked_process.workflow = mocked_workflow
|
|
34
|
+
|
|
35
|
+
# Create a fake process step with a mismatching status.
|
|
36
|
+
mocked_process_step = mocker.MagicMock(spec=ProcessStep)
|
|
37
|
+
mocked_process_step.process = mocked_process
|
|
38
|
+
mocked_process_step.status = "status_b"
|
|
39
|
+
mocked_process_step.step.get_casted_step.return_value = mocked_casted_step
|
|
40
|
+
|
|
41
|
+
return mocked_process_step, mocked_casted_step
|
|
42
|
+
|
|
14
43
|
def test_check_workflow_for_instance_fail_process_steps(
|
|
15
|
-
self,
|
|
44
|
+
self, mocked_instance, mocked_process_step, mocker: MockerFixture
|
|
16
45
|
):
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
)
|
|
25
|
-
process_step2 = process_step_factory(
|
|
26
|
-
step=step,
|
|
27
|
-
state=ProcessStep.StepState.ACTIVE,
|
|
28
|
-
process__state=Process.ProcessState.ACTIVE,
|
|
29
|
-
process__instance=instance,
|
|
30
|
-
)
|
|
31
|
-
process_step_factory(
|
|
32
|
-
step=step,
|
|
33
|
-
state=ProcessStep.StepState.ACTIVE,
|
|
34
|
-
process__state=Process.ProcessState.ACTIVE,
|
|
35
|
-
process__instance=instance,
|
|
36
|
-
status=instance.first_name,
|
|
37
|
-
)
|
|
38
|
-
process_step_factory(
|
|
39
|
-
step=step,
|
|
40
|
-
state=ProcessStep.StepState.CANCELED,
|
|
41
|
-
process__state=Process.ProcessState.ACTIVE,
|
|
42
|
-
process__instance=instance,
|
|
43
|
-
)
|
|
44
|
-
process_step_factory(
|
|
45
|
-
step=step,
|
|
46
|
-
state=ProcessStep.StepState.FAILED,
|
|
47
|
-
process__state=Process.ProcessState.ACTIVE,
|
|
48
|
-
process__instance=instance,
|
|
49
|
-
)
|
|
50
|
-
process_step_factory(
|
|
51
|
-
step=step,
|
|
52
|
-
state=ProcessStep.StepState.FINISHED,
|
|
53
|
-
process__state=Process.ProcessState.ACTIVE,
|
|
54
|
-
process__instance=instance,
|
|
46
|
+
# Arrange
|
|
47
|
+
mocked_process_step, mocked_casted_step = mocked_process_step
|
|
48
|
+
|
|
49
|
+
# Patch ProcessStep.objects.filter to return a fake process step.
|
|
50
|
+
mocker.patch(
|
|
51
|
+
"wbcore.contrib.workflow.models.ProcessStep.objects.filter",
|
|
52
|
+
return_value=[mocked_process_step],
|
|
55
53
|
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
process__instance=instance,
|
|
54
|
+
# Patch get_start_steps_for_instance to return an empty list.
|
|
55
|
+
mocker.patch(
|
|
56
|
+
"wbcore.contrib.workflow.models.Workflow.get_start_steps_for_instance",
|
|
57
|
+
return_value=[],
|
|
61
58
|
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
|
|
60
|
+
# Act
|
|
61
|
+
check_workflow_for_instance(sender=None, instance=mocked_instance, created=True)
|
|
62
|
+
|
|
63
|
+
# Assert: Ensure set_failed was called with the correct arguments.
|
|
64
|
+
mocked_casted_step.set_failed.assert_called_once_with(mocked_process_step, "Invalid status detected!")
|
|
65
|
+
|
|
66
|
+
def test_check_workflow_for_instance_start_workflow(self, mocked_instance, mocker: MockerFixture):
|
|
67
|
+
# Arrange: Create two fake start steps, each with its own workflow.
|
|
68
|
+
fake_start_step1 = mocker.MagicMock()
|
|
69
|
+
fake_workflow1 = mocker.MagicMock(spec=Workflow)
|
|
70
|
+
fake_start_step1.workflow = fake_workflow1
|
|
71
|
+
|
|
72
|
+
fake_start_step2 = mocker.MagicMock()
|
|
73
|
+
fake_workflow2 = mocker.MagicMock(spec=Workflow)
|
|
74
|
+
fake_start_step2.workflow = fake_workflow2
|
|
75
|
+
|
|
76
|
+
# Patch get_start_steps_for_instance to return our fake start steps.
|
|
77
|
+
get_start_steps_patch = mocker.patch(
|
|
78
|
+
"wbcore.contrib.workflow.models.Workflow.get_start_steps_for_instance",
|
|
79
|
+
return_value=[fake_start_step1, fake_start_step2],
|
|
67
80
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
process__instance=PersonFactory(),
|
|
81
|
+
# Patch ProcessStep.objects.filter to return an empty list.
|
|
82
|
+
mocker.patch(
|
|
83
|
+
"wbcore.contrib.workflow.models.ProcessStep.objects.filter",
|
|
84
|
+
return_value=[],
|
|
73
85
|
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
start_step1 = start_step_factory()
|
|
84
|
-
start_step2 = start_step_factory()
|
|
85
|
-
start_step_factory()
|
|
86
|
-
mock_start_steps.return_value = [start_step1, start_step2]
|
|
87
|
-
check_workflow_for_instance(instance.__class__, instance, False)
|
|
88
|
-
assert mock_start_steps.call_args.args == (instance,)
|
|
89
|
-
assert mock_start.call_args_list == [((start_step1, instance),), ((start_step2, instance),)]
|
|
86
|
+
|
|
87
|
+
# Act
|
|
88
|
+
check_workflow_for_instance(sender=None, instance=mocked_instance, created=True)
|
|
89
|
+
|
|
90
|
+
# Assert: Verify that get_start_steps_for_instance was called with our instance.
|
|
91
|
+
get_start_steps_patch.assert_called_once_with(mocked_instance)
|
|
92
|
+
# Verify that each fake workflow's start_workflow was called with its corresponding start step and the instance.
|
|
93
|
+
fake_workflow1.start_workflow.assert_called_once_with(fake_start_step1, mocked_instance)
|
|
94
|
+
fake_workflow2.start_workflow.assert_called_once_with(fake_start_step2, mocked_instance)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import pytest
|
|
2
1
|
from rest_framework.test import APIRequestFactory
|
|
3
2
|
|
|
4
3
|
from wbcore.contrib.color.enums import WBColor
|
|
@@ -9,7 +8,6 @@ from wbcore.contrib.workflow.viewsets.display.process import (
|
|
|
9
8
|
)
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
@pytest.mark.django_db
|
|
13
11
|
class TestProcessStep:
|
|
14
12
|
api_factory = APIRequestFactory()
|
|
15
13
|
|
|
@@ -19,8 +17,16 @@ class TestProcessStep:
|
|
|
19
17
|
(ProcessStep.StepState.CANCELED, WBColor.BLUE_LIGHT.value),
|
|
20
18
|
]
|
|
21
19
|
assert set((y.icon, y.label, y.value) for y in get_state_legend(color_map)[0].items) == {
|
|
22
|
-
(
|
|
23
|
-
|
|
20
|
+
(
|
|
21
|
+
WBColor.GREEN_LIGHT.value,
|
|
22
|
+
ProcessStep.StepState.FAILED.label,
|
|
23
|
+
ProcessStep.StepState.FAILED.value,
|
|
24
|
+
),
|
|
25
|
+
(
|
|
26
|
+
WBColor.BLUE_LIGHT.value,
|
|
27
|
+
ProcessStep.StepState.CANCELED.label,
|
|
28
|
+
ProcessStep.StepState.CANCELED.value,
|
|
29
|
+
),
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
def test_get_state_formatting(self):
|
|
@@ -34,87 +40,3 @@ class TestProcessStep:
|
|
|
34
40
|
(WBColor.GREY.value, ProcessStep.StepState.WAITING.value),
|
|
35
41
|
(WBColor.YELLOW_DARK.value, ProcessStep.StepState.ACTIVE.value),
|
|
36
42
|
}
|
|
37
|
-
|
|
38
|
-
# @patch("wbcore.contrib.workflow.viewsets.display.process.split_list_into_grid_template_area_sublists")
|
|
39
|
-
# def test_process_step_display_instance_injection(
|
|
40
|
-
# self, mock_split, data_factory, user_step_factory, process_step_factory
|
|
41
|
-
# ):
|
|
42
|
-
# request = self.api_factory.get("")
|
|
43
|
-
# request.user = get_or_create_superuser()
|
|
44
|
-
# request.query_params = {}
|
|
45
|
-
# step = user_step_factory()
|
|
46
|
-
# process_step = process_step_factory(step=step)
|
|
47
|
-
# data_factory(workflow=process_step.step.workflow)
|
|
48
|
-
# mvs = ProcessStepModelViewSet(request=request, kwargs={"pk": process_step.pk})
|
|
49
|
-
# display = mvs.display_config_class(mvs, request).get_instance_display()
|
|
50
|
-
# assert display.pages[0].layouts["default"].grid_template_areas == step.display.grid_template_areas
|
|
51
|
-
# assert not mock_split.called
|
|
52
|
-
|
|
53
|
-
# @patch("wbcore.contrib.workflow.viewsets.display.process.split_list_into_grid_template_area_sublists")
|
|
54
|
-
# def test_process_step_display_no_userstep(self, mock_split, random_child_step_factory, process_step_factory):
|
|
55
|
-
# request = self.api_factory.get("")
|
|
56
|
-
# request.user = get_or_create_superuser()
|
|
57
|
-
# request.query_params = {}
|
|
58
|
-
# step = random_child_step_factory(exclude_factories=[UserStepFactory])
|
|
59
|
-
# process_step = process_step_factory(step=step)
|
|
60
|
-
# mvs = ProcessStepModelViewSet(request=request, kwargs={"pk": process_step.pk})
|
|
61
|
-
# display = mvs.display_config_class(mvs, request).get_instance_display()
|
|
62
|
-
# display_fields = set(itertools.chain.from_iterable(display.pages[0].layouts["default"].grid_template_areas))
|
|
63
|
-
# person_fields = set(PersonModelSerializer.Meta.fields)
|
|
64
|
-
# assert not mock_split.called
|
|
65
|
-
# assert display_fields.intersection(person_fields) == {"id"}
|
|
66
|
-
|
|
67
|
-
# @patch("wbcore.contrib.workflow.viewsets.display.process.split_list_into_grid_template_area_sublists")
|
|
68
|
-
# def test_process_step_display_no_display(self, mock_split, user_step_factory, process_step_factory):
|
|
69
|
-
# request = self.api_factory.get("")
|
|
70
|
-
# request.user = get_or_create_superuser()
|
|
71
|
-
# request.query_params = {}
|
|
72
|
-
# step = user_step_factory(display=None)
|
|
73
|
-
# process_step = process_step_factory(step=step)
|
|
74
|
-
# mvs = ProcessStepModelViewSet(request=request, kwargs={"pk": process_step.pk})
|
|
75
|
-
# display = mvs.display_config_class(mvs, request).get_instance_display()
|
|
76
|
-
# display_fields = set(itertools.chain.from_iterable(display.pages[0].layouts["default"].grid_template_areas))
|
|
77
|
-
# person_fields = set(PersonModelSerializer.Meta.fields)
|
|
78
|
-
# assert not mock_split.called
|
|
79
|
-
# assert display_fields.intersection(person_fields) == {"id"}
|
|
80
|
-
|
|
81
|
-
# @patch("wbcore.contrib.workflow.viewsets.display.process.split_list_into_grid_template_area_sublists")
|
|
82
|
-
# def test_process_step_display_data_injection(
|
|
83
|
-
# self, mock_split, data_factory, user_step_factory, process_step_factory
|
|
84
|
-
# ):
|
|
85
|
-
# request = self.api_factory.get("")
|
|
86
|
-
# request.user = get_or_create_superuser()
|
|
87
|
-
# request.query_params = {}
|
|
88
|
-
# step = user_step_factory(display=None)
|
|
89
|
-
# process_step = process_step_factory(step=step)
|
|
90
|
-
# data1 = data_factory(workflow=process_step.process.workflow)
|
|
91
|
-
# data2 = data_factory(workflow=process_step.process.workflow)
|
|
92
|
-
# data_factory()
|
|
93
|
-
# data_sublist = ["a", "b", "c"]
|
|
94
|
-
# mock_split.return_value = data_sublist
|
|
95
|
-
# mvs = ProcessStepModelViewSet(request=request, kwargs={"pk": process_step.pk})
|
|
96
|
-
# display = mvs.display_config_class(mvs, request).get_instance_display()
|
|
97
|
-
# display_fields = set(itertools.chain.from_iterable(display.pages[0].layouts["default"].grid_template_areas))
|
|
98
|
-
# person_fields = set(PersonModelSerializer.Meta.fields)
|
|
99
|
-
# assert display_fields.intersection(person_fields) == {"id"}
|
|
100
|
-
# assert mock_split.call_args.args[0] == [f"data__{str(data1.pk)}", f"data__{str(data2.pk)}"]
|
|
101
|
-
# for key in data_sublist:
|
|
102
|
-
# assert key in display_fields
|
|
103
|
-
|
|
104
|
-
# @patch("wbcore.contrib.workflow.viewsets.display.process.split_list_into_grid_template_area_sublists")
|
|
105
|
-
# def test_process_step_display_no_display_no_data(
|
|
106
|
-
# self, mock_split, data_factory, user_step_factory, process_step_factory
|
|
107
|
-
# ):
|
|
108
|
-
# request = self.api_factory.get("")
|
|
109
|
-
# request.user = get_or_create_superuser()
|
|
110
|
-
# request.query_params = {}
|
|
111
|
-
# step = user_step_factory(display=None)
|
|
112
|
-
# process_step = process_step_factory(step=step)
|
|
113
|
-
# data_factory()
|
|
114
|
-
# data_factory()
|
|
115
|
-
# mvs = ProcessStepModelViewSet(request=request, kwargs={"pk": process_step.pk})
|
|
116
|
-
# display = mvs.display_config_class(mvs, request).get_instance_display()
|
|
117
|
-
# display_fields = set(itertools.chain.from_iterable(display.pages[0].layouts["default"].grid_template_areas))
|
|
118
|
-
# person_fields = set(PersonModelSerializer.Meta.fields)
|
|
119
|
-
# assert display_fields.intersection(person_fields) == {"id"}
|
|
120
|
-
# assert not mock_split.called
|
|
@@ -12,76 +12,93 @@ from wbcore.contrib.workflow.viewsets import (
|
|
|
12
12
|
from wbcore.test.utils import get_or_create_superuser
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
@pytest.fixture()
|
|
16
|
+
def super_user_get_request():
|
|
17
|
+
request = APIRequestFactory().get("")
|
|
18
|
+
request.user = get_or_create_superuser()
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
@pytest.mark.django_db
|
|
16
22
|
class TestWorkflow:
|
|
17
|
-
|
|
23
|
+
@pytest.fixture()
|
|
24
|
+
def workflow_viewset(self):
|
|
25
|
+
return WorkflowModelViewSet()
|
|
18
26
|
|
|
19
|
-
def test_filter_attached_model(self, workflow_factory):
|
|
27
|
+
def test_filter_attached_model(self, super_user_get_request, workflow_viewset, workflow_factory):
|
|
20
28
|
workflow_factory()
|
|
21
29
|
workflow_factory(model=ContentType.objects.first())
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
assert
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
qs = workflow_viewset.get_queryset()
|
|
31
|
+
assert (
|
|
32
|
+
workflow_viewset.filterset_class(request=super_user_get_request).filter_attached_model(qs, "", None) == qs
|
|
33
|
+
)
|
|
34
|
+
assert (
|
|
35
|
+
workflow_viewset.filterset_class(request=super_user_get_request)
|
|
36
|
+
.filter_attached_model(qs, "", "person")
|
|
37
|
+
.count()
|
|
38
|
+
== 1
|
|
39
|
+
)
|
|
40
|
+
assert (
|
|
41
|
+
not workflow_viewset.filterset_class(request=super_user_get_request)
|
|
42
|
+
.filter_attached_model(qs, "", "company")
|
|
43
|
+
.exists()
|
|
44
|
+
)
|
|
29
45
|
|
|
30
|
-
def test_filter_by_data(self, workflow_factory, data_factory):
|
|
46
|
+
def test_filter_by_data(self, super_user_get_request, workflow_viewset, workflow_factory, data_factory):
|
|
31
47
|
workflow_factory()
|
|
32
48
|
data = data_factory()
|
|
33
|
-
|
|
34
|
-
request
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
assert
|
|
39
|
-
|
|
49
|
+
qs = workflow_viewset.get_queryset()
|
|
50
|
+
assert workflow_viewset.filterset_class(request=super_user_get_request).filter_by_data(qs, "", None) == qs
|
|
51
|
+
assert (
|
|
52
|
+
workflow_viewset.filterset_class(request=super_user_get_request).filter_by_data(qs, "", data).count() == 1
|
|
53
|
+
)
|
|
54
|
+
assert (
|
|
55
|
+
workflow_viewset.filterset_class(request=super_user_get_request).filter_by_data(qs, "", data).first()
|
|
56
|
+
== data.workflow
|
|
57
|
+
)
|
|
40
58
|
|
|
41
59
|
|
|
42
60
|
@pytest.mark.django_db
|
|
43
61
|
class TestStep:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def test_filter_by_transition(self, transition_factory, random_child_step_factory):
|
|
62
|
+
def test_filter_by_transition(self, super_user_get_request, transition_factory, random_child_step_factory):
|
|
47
63
|
transition = transition_factory()
|
|
48
64
|
random_child_step_factory()
|
|
49
65
|
mvs = StepModelViewSet(kwargs={})
|
|
50
|
-
request = self.api_factory.get("")
|
|
51
|
-
request.user = get_or_create_superuser()
|
|
52
66
|
qs = mvs.get_queryset()
|
|
53
|
-
assert mvs.get_filterset_class(request=
|
|
54
|
-
assert set(
|
|
55
|
-
|
|
56
|
-
)
|
|
67
|
+
assert mvs.get_filterset_class(request=super_user_get_request)().filter_by_transition(qs, "", None) == qs
|
|
68
|
+
assert set(
|
|
69
|
+
mvs.get_filterset_class(request=super_user_get_request)().filter_by_transition(qs, "", transition)
|
|
70
|
+
) == set(Step.objects.filter(id__in=[transition.from_step.pk, transition.to_step.pk]))
|
|
57
71
|
|
|
58
|
-
def test_email_filter_template_name(self, email_step_factory):
|
|
72
|
+
def test_email_filter_template_name(self, super_user_get_request, email_step_factory):
|
|
59
73
|
step = email_step_factory()
|
|
60
74
|
email_step_factory()
|
|
61
75
|
mvs = EmailStepModelViewSet(kwargs={})
|
|
62
|
-
request = self.api_factory.get("")
|
|
63
|
-
request.user = get_or_create_superuser()
|
|
64
76
|
qs = mvs.get_queryset()
|
|
65
|
-
assert mvs.get_filterset_class(request=
|
|
66
|
-
assert
|
|
77
|
+
assert mvs.get_filterset_class(request=super_user_get_request)().filter_template_name(qs, "", None) == qs
|
|
78
|
+
assert (
|
|
79
|
+
mvs.get_filterset_class(request=super_user_get_request)()
|
|
80
|
+
.filter_template_name(qs, "", step.template.name)
|
|
81
|
+
.count()
|
|
82
|
+
== 1
|
|
83
|
+
)
|
|
67
84
|
assert (
|
|
68
|
-
mvs.get_filterset_class(request=
|
|
85
|
+
mvs.get_filterset_class(request=super_user_get_request)()
|
|
86
|
+
.filter_template_name(qs, "", step.template.name)
|
|
87
|
+
.first()
|
|
88
|
+
== step
|
|
69
89
|
)
|
|
70
90
|
|
|
71
91
|
|
|
72
92
|
@pytest.mark.django_db
|
|
73
93
|
class TestTransition:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def test_filter_by_condition(self, condition_factory, transition_factory):
|
|
94
|
+
def test_filter_by_condition(self, super_user_get_request, condition_factory, transition_factory):
|
|
77
95
|
transition_factory()
|
|
78
96
|
condition = condition_factory()
|
|
79
97
|
mvs = TransitionModelViewSet(kwargs={})
|
|
80
|
-
request = self.api_factory.get("")
|
|
81
|
-
request.user = get_or_create_superuser()
|
|
82
98
|
qs = mvs.get_queryset()
|
|
83
|
-
assert mvs.filterset_class(request=
|
|
84
|
-
assert mvs.filterset_class(request=
|
|
99
|
+
assert mvs.filterset_class(request=super_user_get_request).filter_by_condition(qs, "", None) == qs
|
|
100
|
+
assert mvs.filterset_class(request=super_user_get_request).filter_by_condition(qs, "", condition).count() == 1
|
|
85
101
|
assert (
|
|
86
|
-
mvs.filterset_class(request=
|
|
102
|
+
mvs.filterset_class(request=super_user_get_request).filter_by_condition(qs, "", condition).first()
|
|
103
|
+
== condition.transition
|
|
87
104
|
)
|
|
@@ -1,79 +1,82 @@
|
|
|
1
|
-
from unittest.mock import patch
|
|
2
|
-
|
|
3
1
|
import pytest
|
|
4
|
-
from
|
|
5
|
-
from wbcore.contrib.workflow.models import
|
|
2
|
+
from pytest_mock import MockerFixture
|
|
3
|
+
from wbcore.contrib.workflow.models import DecisionStep, Transition
|
|
6
4
|
|
|
7
5
|
|
|
8
|
-
@pytest.mark.django_db
|
|
9
6
|
class TestDecisionStep:
|
|
7
|
+
@pytest.fixture
|
|
8
|
+
def mocked_instances(self, mocker: MockerFixture):
|
|
9
|
+
return mocker.MagicMock(first_name="John")
|
|
10
|
+
|
|
11
|
+
@pytest.fixture
|
|
12
|
+
def mocked_decision_step(self, mocker: MockerFixture):
|
|
13
|
+
return mocker.MagicMock(spec=DecisionStep)
|
|
14
|
+
|
|
10
15
|
def test_get_first_valid_transition(
|
|
11
|
-
self,
|
|
16
|
+
self,
|
|
17
|
+
mocker: MockerFixture,
|
|
18
|
+
mocked_process_step,
|
|
19
|
+
mocked_instances,
|
|
20
|
+
mocked_decision_step,
|
|
12
21
|
):
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
valid_transition1 =
|
|
17
|
-
valid_transition2 =
|
|
18
|
-
invalid_transition =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
# Arrange
|
|
23
|
+
mocked_process_step.get_instance.return_value = mocked_instances
|
|
24
|
+
mocked_process_step.step = mocked_decision_step
|
|
25
|
+
valid_transition1 = mocker.MagicMock(spec=Transition)
|
|
26
|
+
valid_transition2 = mocker.MagicMock(spec=Transition)
|
|
27
|
+
invalid_transition = mocker.MagicMock(spec=Transition)
|
|
28
|
+
mocked_decision_step.get_outgoing_transitions.return_value = [
|
|
29
|
+
invalid_transition,
|
|
30
|
+
valid_transition1,
|
|
31
|
+
valid_transition2,
|
|
32
|
+
]
|
|
33
|
+
invalid_transition.all_conditions_satisfied.return_value = False
|
|
34
|
+
valid_transition1.all_conditions_satisfied.return_value = True
|
|
35
|
+
valid_transition2.all_conditions_satisfied.return_value = True
|
|
36
|
+
# Act
|
|
37
|
+
result = DecisionStep.get_first_valid_transition(mocked_decision_step, mocked_process_step)
|
|
38
|
+
# Assert
|
|
39
|
+
assert result in [valid_transition1, valid_transition2]
|
|
40
|
+
invalid_transition.all_conditions_satisfied.assert_called_once_with(mocked_process_step)
|
|
41
|
+
valid_transition1.all_conditions_satisfied.assert_called_once_with(mocked_process_step)
|
|
42
|
+
valid_transition2.all_conditions_satisfied.assert_not_called()
|
|
28
43
|
|
|
29
44
|
def test_get_first_valid_transition_no_transitions(
|
|
30
|
-
self,
|
|
45
|
+
self, mocker, mocked_process_step, mocked_instances, mocked_decision_step
|
|
31
46
|
):
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
invalid_transition =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
assert step.get_first_valid_transition(process_step) is None
|
|
47
|
+
# Arrange
|
|
48
|
+
mocked_process_step.get_instance.return_value = mocked_instances
|
|
49
|
+
mocked_process_step.step = mocked_decision_step
|
|
50
|
+
invalid_transition = mocker.MagicMock(spec=Transition)
|
|
51
|
+
mocked_decision_step.get_outgoing_transitions.return_value = [invalid_transition]
|
|
52
|
+
invalid_transition.all_conditions_satisfied.return_value = False
|
|
53
|
+
# Act
|
|
54
|
+
result = DecisionStep.get_first_valid_transition(mocked_decision_step, mocked_process_step)
|
|
55
|
+
# Assert
|
|
56
|
+
assert result is None
|
|
57
|
+
invalid_transition.all_conditions_satisfied.assert_called_once_with(mocked_process_step)
|
|
45
58
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
transition = transition_factory()
|
|
57
|
-
mock_transition.return_value = transition
|
|
58
|
-
step = decision_step_factory()
|
|
59
|
-
process_step = process_step_factory(step=step)
|
|
60
|
-
step.run(process_step)
|
|
61
|
-
assert mock_next.call_args.args == (process_step, transition)
|
|
59
|
+
def test_run(self, mocker: MockerFixture, mocked_process_step, mocked_decision_step):
|
|
60
|
+
# Arrange
|
|
61
|
+
mocked_start_next_step = mocker.patch("wbcore.contrib.workflow.models.step.Step.start_next_step")
|
|
62
|
+
mocked_transition = mocker.MagicMock(spec=Transition)
|
|
63
|
+
mocked_decision_step.get_first_valid_transition.return_value = mocked_transition
|
|
64
|
+
# Act
|
|
65
|
+
DecisionStep.run(mocked_decision_step, mocked_process_step)
|
|
66
|
+
# Assert
|
|
67
|
+
mocked_decision_step.get_first_valid_transition.assert_called_once_with(mocked_process_step)
|
|
68
|
+
mocked_start_next_step.assert_called_once_with(mocked_process_step, mocked_transition)
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
process_step = process_step_factory(step=step)
|
|
77
|
-
step.run(process_step)
|
|
78
|
-
assert mock_failed.call_args.args[0] == process_step
|
|
79
|
-
assert not mock_activate.called
|
|
70
|
+
def test_run_failed(self, mocker: MockerFixture, mocked_process_step, mocked_decision_step):
|
|
71
|
+
# Arrange
|
|
72
|
+
mocked_activate_step = mocker.patch("wbcore.contrib.workflow.models.step.activate_step.delay")
|
|
73
|
+
mocked_decision_step.get_first_valid_transition.return_value = None
|
|
74
|
+
mocked_set_failed = mocker.patch.object(mocked_decision_step, "set_failed")
|
|
75
|
+
# Act
|
|
76
|
+
DecisionStep.run(mocked_decision_step, mocked_process_step)
|
|
77
|
+
# Assert
|
|
78
|
+
mocked_decision_step.get_first_valid_transition.assert_called_once_with(mocked_process_step)
|
|
79
|
+
mocked_set_failed.assert_called_once_with(
|
|
80
|
+
mocked_process_step, "No valid outgoing transition found for this step!"
|
|
81
|
+
)
|
|
82
|
+
mocked_activate_step.assert_not_called()
|