wbcrm 1.56.8__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.
- wbcrm/__init__.py +1 -0
- wbcrm/admin/__init__.py +5 -0
- wbcrm/admin/accounts.py +60 -0
- wbcrm/admin/activities.py +104 -0
- wbcrm/admin/events.py +43 -0
- wbcrm/admin/groups.py +8 -0
- wbcrm/admin/products.py +9 -0
- wbcrm/apps.py +5 -0
- wbcrm/configurations/__init__.py +1 -0
- wbcrm/configurations/base.py +16 -0
- wbcrm/dynamic_preferences_registry.py +38 -0
- wbcrm/factories/__init__.py +14 -0
- wbcrm/factories/accounts.py +57 -0
- wbcrm/factories/activities.py +124 -0
- wbcrm/factories/groups.py +24 -0
- wbcrm/factories/products.py +11 -0
- wbcrm/filters/__init__.py +10 -0
- wbcrm/filters/accounts.py +80 -0
- wbcrm/filters/activities.py +204 -0
- wbcrm/filters/groups.py +21 -0
- wbcrm/filters/products.py +38 -0
- wbcrm/filters/signals.py +95 -0
- wbcrm/fixtures/wbcrm.json +1215 -0
- wbcrm/kpi_handlers/activities.py +171 -0
- wbcrm/locale/de/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/de/LC_MESSAGES/django.po +1557 -0
- wbcrm/locale/de/LC_MESSAGES/django.po.translated +1630 -0
- wbcrm/locale/en/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/en/LC_MESSAGES/django.po +1466 -0
- wbcrm/locale/fr/LC_MESSAGES/django.mo +0 -0
- wbcrm/locale/fr/LC_MESSAGES/django.po +1467 -0
- wbcrm/migrations/0001_initial_squashed_squashed_0032_productcompanyrelationship_alter_product_prospects_and_more.py +3948 -0
- wbcrm/migrations/0002_alter_activity_repeat_choice.py +32 -0
- wbcrm/migrations/0003_remove_activity_external_id_and_more.py +63 -0
- wbcrm/migrations/0004_alter_activity_status.py +28 -0
- wbcrm/migrations/0005_account_accountrole_accountroletype_and_more.py +182 -0
- wbcrm/migrations/0006_alter_activity_location.py +17 -0
- wbcrm/migrations/0007_alter_account_status.py +23 -0
- wbcrm/migrations/0008_alter_activity_options.py +16 -0
- wbcrm/migrations/0009_alter_account_is_public.py +19 -0
- wbcrm/migrations/0010_alter_account_reference_id.py +17 -0
- wbcrm/migrations/0011_activity_summary.py +22 -0
- wbcrm/migrations/0012_alter_activity_summary.py +17 -0
- wbcrm/migrations/0013_account_action_plan_account_relationship_status_and_more.py +34 -0
- wbcrm/migrations/0014_alter_account_relationship_status.py +24 -0
- wbcrm/migrations/0015_alter_activity_type.py +23 -0
- wbcrm/migrations/0016_auto_20241205_1015.py +106 -0
- wbcrm/migrations/0017_event.py +40 -0
- wbcrm/migrations/0018_activity_search_vector.py +24 -0
- wbcrm/migrations/__init__.py +0 -0
- wbcrm/models/__init__.py +5 -0
- wbcrm/models/accounts.py +648 -0
- wbcrm/models/activities.py +1419 -0
- wbcrm/models/events.py +15 -0
- wbcrm/models/groups.py +119 -0
- wbcrm/models/llm/activity_summaries.py +41 -0
- wbcrm/models/llm/analyze_relationship.py +50 -0
- wbcrm/models/products.py +86 -0
- wbcrm/models/recurrence.py +280 -0
- wbcrm/preferences.py +13 -0
- wbcrm/report/activity_report.py +110 -0
- wbcrm/serializers/__init__.py +23 -0
- wbcrm/serializers/accounts.py +141 -0
- wbcrm/serializers/activities.py +525 -0
- wbcrm/serializers/groups.py +30 -0
- wbcrm/serializers/products.py +58 -0
- wbcrm/serializers/recurrence.py +91 -0
- wbcrm/serializers/signals.py +71 -0
- wbcrm/static/wbcrm/markdown/documentation/activity.md +86 -0
- wbcrm/static/wbcrm/markdown/documentation/activitytype.md +20 -0
- wbcrm/static/wbcrm/markdown/documentation/group.md +2 -0
- wbcrm/static/wbcrm/markdown/documentation/product.md +11 -0
- wbcrm/synchronization/__init__.py +0 -0
- wbcrm/synchronization/activity/__init__.py +0 -0
- wbcrm/synchronization/activity/admin.py +73 -0
- wbcrm/synchronization/activity/backend.py +214 -0
- wbcrm/synchronization/activity/backends/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/google/__init__.py +2 -0
- wbcrm/synchronization/activity/backends/google/google_calendar_backend.py +406 -0
- wbcrm/synchronization/activity/backends/google/request_utils/__init__.py +16 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/create.py +75 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/delete.py +78 -0
- wbcrm/synchronization/activity/backends/google/request_utils/external_to_internal/update.py +155 -0
- wbcrm/synchronization/activity/backends/google/request_utils/internal_to_external/update.py +181 -0
- wbcrm/synchronization/activity/backends/google/tasks.py +21 -0
- wbcrm/synchronization/activity/backends/google/tests/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/google/tests/conftest.py +1 -0
- wbcrm/synchronization/activity/backends/google/tests/test_data.py +81 -0
- wbcrm/synchronization/activity/backends/google/tests/test_google_backend.py +319 -0
- wbcrm/synchronization/activity/backends/google/tests/test_utils.py +274 -0
- wbcrm/synchronization/activity/backends/google/typing_informations.py +139 -0
- wbcrm/synchronization/activity/backends/google/utils.py +217 -0
- wbcrm/synchronization/activity/backends/outlook/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/outlook/backend.py +593 -0
- wbcrm/synchronization/activity/backends/outlook/msgraph.py +436 -0
- wbcrm/synchronization/activity/backends/outlook/parser.py +432 -0
- wbcrm/synchronization/activity/backends/outlook/tests/__init__.py +0 -0
- wbcrm/synchronization/activity/backends/outlook/tests/conftest.py +1 -0
- wbcrm/synchronization/activity/backends/outlook/tests/fixtures.py +606 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_admin.py +118 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_backend.py +274 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_controller.py +249 -0
- wbcrm/synchronization/activity/backends/outlook/tests/test_parser.py +174 -0
- wbcrm/synchronization/activity/controller.py +627 -0
- wbcrm/synchronization/activity/dynamic_preferences_registry.py +119 -0
- wbcrm/synchronization/activity/preferences.py +27 -0
- wbcrm/synchronization/activity/shortcuts.py +16 -0
- wbcrm/synchronization/activity/tasks.py +21 -0
- wbcrm/synchronization/activity/urls.py +7 -0
- wbcrm/synchronization/activity/utils.py +46 -0
- wbcrm/synchronization/activity/views.py +41 -0
- wbcrm/synchronization/admin.py +1 -0
- wbcrm/synchronization/apps.py +14 -0
- wbcrm/synchronization/dynamic_preferences_registry.py +1 -0
- wbcrm/synchronization/management.py +36 -0
- wbcrm/synchronization/tasks.py +1 -0
- wbcrm/synchronization/urls.py +5 -0
- wbcrm/tasks.py +264 -0
- wbcrm/templates/email/activity.html +98 -0
- wbcrm/templates/email/activity_report.html +6 -0
- wbcrm/templates/email/daily_summary.html +72 -0
- wbcrm/templates/email/global_daily_summary.html +85 -0
- wbcrm/tests/__init__.py +0 -0
- wbcrm/tests/accounts/__init__.py +0 -0
- wbcrm/tests/accounts/test_models.py +393 -0
- wbcrm/tests/accounts/test_viewsets.py +88 -0
- wbcrm/tests/conftest.py +76 -0
- wbcrm/tests/disable_signals.py +62 -0
- wbcrm/tests/e2e/__init__.py +1 -0
- wbcrm/tests/e2e/e2e_wbcrm_utility.py +83 -0
- wbcrm/tests/e2e/test_e2e.py +370 -0
- wbcrm/tests/test_assignee_methods.py +40 -0
- wbcrm/tests/test_chartviewsets.py +112 -0
- wbcrm/tests/test_dto.py +64 -0
- wbcrm/tests/test_filters.py +52 -0
- wbcrm/tests/test_models.py +217 -0
- wbcrm/tests/test_recurrence.py +292 -0
- wbcrm/tests/test_report.py +21 -0
- wbcrm/tests/test_serializers.py +171 -0
- wbcrm/tests/test_tasks.py +95 -0
- wbcrm/tests/test_viewsets.py +967 -0
- wbcrm/tests/tests.py +121 -0
- wbcrm/typings.py +109 -0
- wbcrm/urls.py +67 -0
- wbcrm/viewsets/__init__.py +22 -0
- wbcrm/viewsets/accounts.py +122 -0
- wbcrm/viewsets/activities.py +341 -0
- wbcrm/viewsets/buttons/__init__.py +7 -0
- wbcrm/viewsets/buttons/accounts.py +27 -0
- wbcrm/viewsets/buttons/activities.py +89 -0
- wbcrm/viewsets/buttons/signals.py +17 -0
- wbcrm/viewsets/display/__init__.py +12 -0
- wbcrm/viewsets/display/accounts.py +110 -0
- wbcrm/viewsets/display/activities.py +444 -0
- wbcrm/viewsets/display/groups.py +22 -0
- wbcrm/viewsets/display/products.py +105 -0
- wbcrm/viewsets/endpoints/__init__.py +8 -0
- wbcrm/viewsets/endpoints/accounts.py +25 -0
- wbcrm/viewsets/endpoints/activities.py +30 -0
- wbcrm/viewsets/endpoints/groups.py +7 -0
- wbcrm/viewsets/endpoints/products.py +9 -0
- wbcrm/viewsets/groups.py +38 -0
- wbcrm/viewsets/menu/__init__.py +8 -0
- wbcrm/viewsets/menu/accounts.py +18 -0
- wbcrm/viewsets/menu/activities.py +49 -0
- wbcrm/viewsets/menu/groups.py +16 -0
- wbcrm/viewsets/menu/products.py +20 -0
- wbcrm/viewsets/mixins.py +35 -0
- wbcrm/viewsets/previews/__init__.py +1 -0
- wbcrm/viewsets/previews/activities.py +10 -0
- wbcrm/viewsets/products.py +57 -0
- wbcrm/viewsets/recurrence.py +27 -0
- wbcrm/viewsets/titles/__init__.py +13 -0
- wbcrm/viewsets/titles/accounts.py +23 -0
- wbcrm/viewsets/titles/activities.py +61 -0
- wbcrm/viewsets/titles/products.py +13 -0
- wbcrm/viewsets/titles/utils.py +46 -0
- wbcrm/workflows/__init__.py +1 -0
- wbcrm/workflows/assignee_methods.py +25 -0
- wbcrm-1.56.8.dist-info/METADATA +11 -0
- wbcrm-1.56.8.dist-info/RECORD +182 -0
- wbcrm-1.56.8.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from selenium.webdriver.remote.webdriver import WebDriver
|
|
2
|
+
from wbcore.contrib.directory.factories import PersonFactory
|
|
3
|
+
from wbcore.contrib.directory.models import Person
|
|
4
|
+
from wbcore.test import (
|
|
5
|
+
click_element_by_path,
|
|
6
|
+
fill_out_form_fields,
|
|
7
|
+
open_create_instance,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from wbcrm.factories import ActivityFactory, ActivityTypeFactory
|
|
11
|
+
from wbcrm.models import Activity, ActivityType
|
|
12
|
+
from wbcrm.serializers import ActivityModelSerializer
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def set_up_activities(creator: Person = None):
|
|
16
|
+
"""Sets up three activities for testing purposes with fixed participants, types and titles.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
creator (Person | None, optional): The person that is used as the activities creator. Defaults to None.
|
|
20
|
+
"""
|
|
21
|
+
type_a = ActivityTypeFactory(title="Meeting")
|
|
22
|
+
type_b = ActivityTypeFactory(title="Call")
|
|
23
|
+
participant_a = PersonFactory(last_name="Turing")
|
|
24
|
+
participant_b = PersonFactory(last_name="Zuse")
|
|
25
|
+
participant_c = PersonFactory(last_name="Lovelace")
|
|
26
|
+
activity_creator = creator if creator else PersonFactory()
|
|
27
|
+
ActivityFactory(
|
|
28
|
+
title="Activity A",
|
|
29
|
+
type=type_a,
|
|
30
|
+
creator=activity_creator,
|
|
31
|
+
preceded_by=None,
|
|
32
|
+
participants=[participant_a, participant_c],
|
|
33
|
+
status=Activity.Status.PLANNED,
|
|
34
|
+
)
|
|
35
|
+
ActivityFactory(
|
|
36
|
+
title="Activity B",
|
|
37
|
+
type=type_a,
|
|
38
|
+
creator=activity_creator,
|
|
39
|
+
preceded_by=None,
|
|
40
|
+
participants=[participant_a, participant_b],
|
|
41
|
+
status=Activity.Status.FINISHED,
|
|
42
|
+
)
|
|
43
|
+
ActivityFactory(
|
|
44
|
+
title="Activity C",
|
|
45
|
+
type=type_b,
|
|
46
|
+
creator=activity_creator,
|
|
47
|
+
preceded_by=None,
|
|
48
|
+
participants=[participant_b, participant_c],
|
|
49
|
+
status=Activity.Status.PLANNED,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def create_new_activity_instance(
|
|
54
|
+
driver: WebDriver,
|
|
55
|
+
field_list: list[str],
|
|
56
|
+
type_title="",
|
|
57
|
+
activity_title="",
|
|
58
|
+
is_create_instance_open=True,
|
|
59
|
+
) -> Activity:
|
|
60
|
+
"""A function that automatically creates a new activity for selenium e2e-tests.
|
|
61
|
+
After creating the instance this function will close the create-widget.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
driver (WebDriver): The Selenium webdriver.
|
|
65
|
+
field_list (list[str]): List of fields to be filled in the creation mask. The field names must match the names in the ActivitySerializer.
|
|
66
|
+
type_title (str, optional): The title of the activity type. Defaults to "".
|
|
67
|
+
activity_title (str, optional): The title of the activity. Defaults to "".
|
|
68
|
+
is_create_instance_open (bool, optional): Should be true if the create-widget is already open. Defaults to True.
|
|
69
|
+
"""
|
|
70
|
+
if not is_create_instance_open:
|
|
71
|
+
open_create_instance(driver, "CRM", "Create Activity")
|
|
72
|
+
|
|
73
|
+
type_title = type_title if type_title else "Test Activity Type"
|
|
74
|
+
activity_title = activity_title if activity_title else "Test Activity"
|
|
75
|
+
if ActivityType.objects.filter(title=activity_title).exists():
|
|
76
|
+
activity_type = ActivityType.objects.get(title=activity_title)
|
|
77
|
+
else:
|
|
78
|
+
activity_type = ActivityTypeFactory(title=type_title)
|
|
79
|
+
activity = ActivityFactory.build(title=activity_title, type=activity_type)
|
|
80
|
+
serializer = ActivityModelSerializer(activity)
|
|
81
|
+
fill_out_form_fields(driver, serializer, field_list, activity)
|
|
82
|
+
click_element_by_path(driver, "//button[@label='Save and close']")
|
|
83
|
+
return activity
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from django.utils import timezone
|
|
5
|
+
from psycopg.types.range import DateRange
|
|
6
|
+
from selenium.webdriver.common.action_chains import ActionChains
|
|
7
|
+
from wbcore.contrib.authentication.factories import SuperUserFactory
|
|
8
|
+
from wbcore.contrib.authentication.models import User
|
|
9
|
+
from wbcore.contrib.authentication.tests.e2e import create_main_company_user
|
|
10
|
+
from wbcore.contrib.directory.models import (
|
|
11
|
+
Company,
|
|
12
|
+
EmployerEmployeeRelationship,
|
|
13
|
+
Person,
|
|
14
|
+
)
|
|
15
|
+
from wbcore.contrib.directory.serializers import (
|
|
16
|
+
ClientManagerModelSerializer,
|
|
17
|
+
CompanyModelSerializer,
|
|
18
|
+
PersonModelSerializer,
|
|
19
|
+
)
|
|
20
|
+
from wbcore.contrib.directory.tests.e2e import (
|
|
21
|
+
create_new_cmr_instance,
|
|
22
|
+
create_new_company_instance,
|
|
23
|
+
create_new_person_instance,
|
|
24
|
+
set_up_companies,
|
|
25
|
+
set_up_persons,
|
|
26
|
+
)
|
|
27
|
+
from wbcore.contrib.directory.viewsets.display import ClientManagerRelationshipColor
|
|
28
|
+
from wbcore.test import (
|
|
29
|
+
click_button_by_label,
|
|
30
|
+
click_close_all_widgets,
|
|
31
|
+
click_new_button,
|
|
32
|
+
delete_list_entry,
|
|
33
|
+
does_background_color_match,
|
|
34
|
+
edit_list_instance,
|
|
35
|
+
find_element_by_text,
|
|
36
|
+
is_counter_as_expected,
|
|
37
|
+
is_error_visible,
|
|
38
|
+
is_string_not_visible,
|
|
39
|
+
is_tag_not_visible,
|
|
40
|
+
is_tag_visible,
|
|
41
|
+
is_text_visible,
|
|
42
|
+
navigate_to_filter,
|
|
43
|
+
open_menu_item,
|
|
44
|
+
select_async_filter,
|
|
45
|
+
select_column_filter,
|
|
46
|
+
select_filter,
|
|
47
|
+
set_up,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
from wbcrm.factories import ActivityFactory
|
|
51
|
+
from wbcrm.models import Activity
|
|
52
|
+
from wbcrm.serializers import ActivityModelSerializer
|
|
53
|
+
from wbcrm.tests.e2e import create_new_activity_instance, set_up_activities
|
|
54
|
+
|
|
55
|
+
USER_PASSWORD = "User_Password"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@pytest.mark.skip(reason="no way of currently testing this")
|
|
59
|
+
@pytest.mark.django_db
|
|
60
|
+
class TestCRMFilters:
|
|
61
|
+
def test_entry_filter(self, live_server, selenium):
|
|
62
|
+
"""
|
|
63
|
+
Testing the "Entry"-Filter.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# Creating a test user
|
|
67
|
+
user: User = SuperUserFactory(plaintext_password=USER_PASSWORD) # noqa
|
|
68
|
+
# Creating three test companies with different last activities.
|
|
69
|
+
companies = set_up_companies()
|
|
70
|
+
now = timezone.now()
|
|
71
|
+
period_a = DateRange(now - datetime.timedelta(days=15, hours=2), now - datetime.timedelta(days=15))
|
|
72
|
+
period_b = DateRange(now - datetime.timedelta(days=60, hours=2), now - datetime.timedelta(days=60))
|
|
73
|
+
ActivityFactory(period=period_a, companies=[companies[0]])
|
|
74
|
+
ActivityFactory(period=period_b, companies=[companies[1], companies[2]])
|
|
75
|
+
|
|
76
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
77
|
+
navigate_to_filter(selenium, "CRM", "Companies")
|
|
78
|
+
|
|
79
|
+
# And the beginning all three companies should be visible, since no filter is set.
|
|
80
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
81
|
+
|
|
82
|
+
# With no filters selected the there should be a message with the hint "No filter criteria yet"
|
|
83
|
+
assert is_text_visible(selenium, "No filter criteria yet")
|
|
84
|
+
|
|
85
|
+
# Select a "No Activity" - filter. Filtering for all companies, that had no activity in the last month.
|
|
86
|
+
select_filter(selenium, "No Activity:", "Last Month")
|
|
87
|
+
|
|
88
|
+
# The "No filter criteria yet" text should now be gone and instead there should be a "filter-tag" with "Last Month".
|
|
89
|
+
assert is_string_not_visible(selenium, "No filter criteria yet")
|
|
90
|
+
assert is_tag_visible(selenium, "Last Month")
|
|
91
|
+
|
|
92
|
+
# Only two companies should be listed, since one company had an activity withing the last month.
|
|
93
|
+
assert is_text_visible(selenium, "Company B")
|
|
94
|
+
assert is_text_visible(selenium, "Company C")
|
|
95
|
+
assert is_string_not_visible(selenium, "Company A")
|
|
96
|
+
assert is_counter_as_expected(selenium, 2)
|
|
97
|
+
|
|
98
|
+
# Selecting an additional column filter to filter by company type.
|
|
99
|
+
select_column_filter(selenium, "Type", "Type A")
|
|
100
|
+
|
|
101
|
+
# After selecting the additional filter there should also be an additional filter tag corresponding to the filter and the number of companies should be one.
|
|
102
|
+
assert is_tag_visible(selenium, "Last Month")
|
|
103
|
+
assert is_tag_visible(selenium, "Type A")
|
|
104
|
+
assert is_counter_as_expected(selenium, 1)
|
|
105
|
+
assert is_text_visible(selenium, "Company B")
|
|
106
|
+
assert is_string_not_visible(selenium, "Company C")
|
|
107
|
+
|
|
108
|
+
# Resetting the filters
|
|
109
|
+
click_button_by_label(selenium, "Clear all filters")
|
|
110
|
+
assert is_text_visible(selenium, "No filter criteria yet")
|
|
111
|
+
assert is_tag_not_visible(selenium, "Type A")
|
|
112
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
113
|
+
|
|
114
|
+
# Close all widgets and switch to the person list
|
|
115
|
+
click_close_all_widgets(selenium)
|
|
116
|
+
set_up_persons()
|
|
117
|
+
navigate_to_filter(selenium, "Persons")
|
|
118
|
+
|
|
119
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
120
|
+
assert is_text_visible(selenium, "No filter criteria yet")
|
|
121
|
+
|
|
122
|
+
# Select a "Specializations" - filter. Filtering for all persons with "Specialization C".
|
|
123
|
+
select_async_filter(selenium, "Specializations:", "Specialization C")
|
|
124
|
+
assert is_tag_visible(selenium, "Specialization C")
|
|
125
|
+
assert is_string_not_visible(selenium, "No filter criteria yet")
|
|
126
|
+
|
|
127
|
+
# Only two persons should be listed
|
|
128
|
+
assert is_string_not_visible(selenium, "Henry Kalb")
|
|
129
|
+
assert is_text_visible(selenium, "Konrad Zuse")
|
|
130
|
+
assert is_text_visible(selenium, "Ada Lovelace")
|
|
131
|
+
filter_count = Person.objects.filter(specializations__title="Specialization C").count()
|
|
132
|
+
assert is_counter_as_expected(selenium, filter_count)
|
|
133
|
+
|
|
134
|
+
# Selecting an additional column filter to filter by person status.
|
|
135
|
+
select_column_filter(selenium, "Status", "Status C")
|
|
136
|
+
|
|
137
|
+
# After selecting the additional filter there should also be an additional filter tag corresponding to the filter and the number of persons should be one.
|
|
138
|
+
assert is_tag_visible(selenium, "Specialization C")
|
|
139
|
+
assert is_tag_visible(selenium, "Status C")
|
|
140
|
+
assert is_string_not_visible(selenium, "Konrad Zuse")
|
|
141
|
+
assert is_text_visible(selenium, "Ada Lovelace")
|
|
142
|
+
filter_count = EmployerEmployeeRelationship.objects.filter(
|
|
143
|
+
employer__in=Company.objects.filter(customer_status__title="Status C"),
|
|
144
|
+
employee__in=Person.objects.filter(specializations__title="Specialization C"),
|
|
145
|
+
primary=True,
|
|
146
|
+
)
|
|
147
|
+
assert is_counter_as_expected(selenium, filter_count)
|
|
148
|
+
|
|
149
|
+
def test_activity_filter(self, live_server, selenium):
|
|
150
|
+
"""
|
|
151
|
+
Testing the "Type" and "Status" - Filter
|
|
152
|
+
"""
|
|
153
|
+
# Creating a test user and setting up selenium
|
|
154
|
+
user: User = SuperUserFactory(plaintext_password=USER_PASSWORD)
|
|
155
|
+
set_up_activities(user.profile)
|
|
156
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
157
|
+
|
|
158
|
+
navigate_to_filter(selenium, "CRM", "Activities")
|
|
159
|
+
|
|
160
|
+
# And the beginning all three activities should be visible, since no filter is set.
|
|
161
|
+
filter_count = Activity.objects.all().count()
|
|
162
|
+
assert is_counter_as_expected(selenium, filter_count)
|
|
163
|
+
|
|
164
|
+
# With no filters selected the there should be a message with the hint "No filter criteria yet"
|
|
165
|
+
assert is_text_visible(selenium, "No filter criteria yet")
|
|
166
|
+
|
|
167
|
+
# Selecting a column filter to filter by activity type.
|
|
168
|
+
select_column_filter(selenium, "Type", "Meeting")
|
|
169
|
+
|
|
170
|
+
assert is_string_not_visible(selenium, "No filter criteria yet")
|
|
171
|
+
assert is_tag_visible(selenium, "Meeting")
|
|
172
|
+
|
|
173
|
+
# After filtering for the type there should be only two activities displayed
|
|
174
|
+
filter_count = Activity.objects.filter(type__title="Meeting").count()
|
|
175
|
+
assert is_counter_as_expected(selenium, filter_count)
|
|
176
|
+
assert is_text_visible(selenium, "Activity A")
|
|
177
|
+
assert is_text_visible(selenium, "Activity B")
|
|
178
|
+
assert is_string_not_visible(selenium, "Activity C")
|
|
179
|
+
|
|
180
|
+
# Select a "Status" - filter. Filtering for all activities, that have the status "Finished".
|
|
181
|
+
select_filter(selenium, "Status:", "Finished")
|
|
182
|
+
|
|
183
|
+
assert is_string_not_visible(selenium, "Activity A")
|
|
184
|
+
assert is_text_visible(selenium, "Activity B")
|
|
185
|
+
filter_count = Activity.objects.filter(type__title="Meeting", status=Activity.Status.FINISHED).count()
|
|
186
|
+
assert is_counter_as_expected(selenium, filter_count)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@pytest.mark.skip(reason="no way of currently testing this")
|
|
190
|
+
@pytest.mark.django_db
|
|
191
|
+
class TestCRMActivities:
|
|
192
|
+
def test_create_edit_delete_activity(self, live_server, selenium):
|
|
193
|
+
"""
|
|
194
|
+
Creates, edits and deletes an activity.
|
|
195
|
+
"""
|
|
196
|
+
# Creating a test user and setting up selenium
|
|
197
|
+
user: User = SuperUserFactory(plaintext_password=USER_PASSWORD)
|
|
198
|
+
actions = ActionChains(selenium, 1000)
|
|
199
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
200
|
+
|
|
201
|
+
# # -----> CREATE <----- #
|
|
202
|
+
activity_a = create_new_activity_instance(selenium, ["title", "type"], "Type A", "Activity A", False)
|
|
203
|
+
open_menu_item(selenium, "Activities", perform_mouse_move=True)
|
|
204
|
+
assert is_text_visible(selenium, activity_a.title)
|
|
205
|
+
assert is_counter_as_expected(selenium, Activity.objects.count())
|
|
206
|
+
|
|
207
|
+
click_new_button(selenium)
|
|
208
|
+
assert is_text_visible(selenium, "New Activity")
|
|
209
|
+
|
|
210
|
+
# Trying to create an activity without filling out anything -> We expect an error to be thrown.
|
|
211
|
+
click_button_by_label(selenium, "Save and close")
|
|
212
|
+
assert is_error_visible(selenium)
|
|
213
|
+
|
|
214
|
+
activity_b = create_new_activity_instance(selenium, ["title", "type"], None, "Activity B")
|
|
215
|
+
assert is_text_visible(selenium, activity_b.title)
|
|
216
|
+
assert is_counter_as_expected(selenium, Activity.objects.count())
|
|
217
|
+
|
|
218
|
+
# -----> Edit <----- #
|
|
219
|
+
|
|
220
|
+
edit_list_instance(selenium, actions, activity_a, ActivityModelSerializer(activity_a), {"title": "A Activity"})
|
|
221
|
+
|
|
222
|
+
assert is_string_not_visible(selenium, "Activity A")
|
|
223
|
+
assert is_text_visible(selenium, "A Activity")
|
|
224
|
+
assert is_counter_as_expected(selenium, Activity.objects.count())
|
|
225
|
+
|
|
226
|
+
# -----> Delete <----- #
|
|
227
|
+
delete_list_entry(selenium, actions, activity_b.title)
|
|
228
|
+
assert is_counter_as_expected(selenium, Activity.objects.count())
|
|
229
|
+
assert is_string_not_visible(selenium, "Activity A")
|
|
230
|
+
assert is_string_not_visible(selenium, "Activity B")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@pytest.mark.skip(reason="no way of currently testing this")
|
|
234
|
+
@pytest.mark.django_db
|
|
235
|
+
class TestCRMEntries:
|
|
236
|
+
def test_create_edit_delete_company(self, live_server, selenium):
|
|
237
|
+
"""
|
|
238
|
+
Creating a new company from the company list view. After creating the company it should be displayed in the company list view.
|
|
239
|
+
"""
|
|
240
|
+
# Creating a test user
|
|
241
|
+
user: User = SuperUserFactory(plaintext_password=USER_PASSWORD)
|
|
242
|
+
actions = ActionChains(selenium, 1000)
|
|
243
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
244
|
+
|
|
245
|
+
# -----> CREATE <----- #
|
|
246
|
+
company_a = create_new_company_instance(
|
|
247
|
+
selenium, ["name", "customer_status"], "Company A", "Test Status", False
|
|
248
|
+
)
|
|
249
|
+
open_menu_item(selenium, "Companies", perform_mouse_move=True)
|
|
250
|
+
assert is_text_visible(selenium, company_a.name)
|
|
251
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
252
|
+
|
|
253
|
+
click_new_button(selenium)
|
|
254
|
+
assert is_text_visible(selenium, "New Company")
|
|
255
|
+
|
|
256
|
+
# Trying to create an activity without filling out anything -> We expect an error to be thrown.
|
|
257
|
+
click_button_by_label(selenium, "Save and close")
|
|
258
|
+
assert is_error_visible(selenium)
|
|
259
|
+
company_b = create_new_company_instance(selenium, ["name", "customer_status"], "Company B")
|
|
260
|
+
|
|
261
|
+
assert is_text_visible(selenium, company_b.name)
|
|
262
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
263
|
+
|
|
264
|
+
# -----> Edit <----- #
|
|
265
|
+
|
|
266
|
+
edit_list_instance(selenium, actions, company_a.name, CompanyModelSerializer(company_a), {"name": "A Company"})
|
|
267
|
+
assert is_string_not_visible(selenium, "Company A")
|
|
268
|
+
assert is_text_visible(selenium, "A Company")
|
|
269
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
270
|
+
|
|
271
|
+
# -----> Delete <----- #
|
|
272
|
+
|
|
273
|
+
delete_list_entry(selenium, actions, company_b.name)
|
|
274
|
+
assert is_counter_as_expected(selenium, Company.objects.count())
|
|
275
|
+
assert is_text_visible(selenium, "A Company")
|
|
276
|
+
assert is_string_not_visible(selenium, "Company A")
|
|
277
|
+
assert is_string_not_visible(selenium, "Company B")
|
|
278
|
+
|
|
279
|
+
def test_create_edit_delete_person(self, live_server, selenium):
|
|
280
|
+
"""
|
|
281
|
+
Creating a new person from the person list view. After creating the person it should be displayed in the person list view.
|
|
282
|
+
"""
|
|
283
|
+
# Creating a test user
|
|
284
|
+
user: User = SuperUserFactory(plaintext_password=USER_PASSWORD)
|
|
285
|
+
actions = ActionChains(selenium, 1000)
|
|
286
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
287
|
+
|
|
288
|
+
# -----> CREATE <----- #
|
|
289
|
+
person_a = create_new_person_instance(
|
|
290
|
+
selenium, ["first_name", "last_name", "prefix"], "Max", "Mustermann", "Mr.", False
|
|
291
|
+
)
|
|
292
|
+
open_menu_item(selenium, "Persons", perform_mouse_move=True)
|
|
293
|
+
assert is_text_visible(selenium, f"{person_a.first_name} {person_a.last_name}")
|
|
294
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
295
|
+
|
|
296
|
+
click_new_button(selenium)
|
|
297
|
+
assert is_text_visible(selenium, "New Person")
|
|
298
|
+
|
|
299
|
+
# Trying to create an activity without filling out anything -> We expect an error to be thrown.
|
|
300
|
+
click_button_by_label(selenium, "Save and close")
|
|
301
|
+
assert is_error_visible(selenium)
|
|
302
|
+
person_b = create_new_person_instance(
|
|
303
|
+
selenium, ["first_name", "last_name", "prefix"], "Maike", "Musterfrau", "Mrs.", False
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
assert is_text_visible(selenium, f"{person_b.first_name} {person_b.last_name}")
|
|
307
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
308
|
+
|
|
309
|
+
# -----> Edit <----- #
|
|
310
|
+
|
|
311
|
+
edit_list_instance(
|
|
312
|
+
selenium,
|
|
313
|
+
actions,
|
|
314
|
+
f"{person_a.first_name} {person_a.last_name}",
|
|
315
|
+
PersonModelSerializer(person_a),
|
|
316
|
+
{"first_name": "Maxissimus"},
|
|
317
|
+
)
|
|
318
|
+
assert is_string_not_visible(selenium, "Max Mustermann")
|
|
319
|
+
assert is_text_visible(selenium, "Maxissimus Mustermann")
|
|
320
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
321
|
+
|
|
322
|
+
# -----> Delete <----- #
|
|
323
|
+
|
|
324
|
+
delete_list_entry(selenium, actions, f"{person_b.first_name} {person_b.last_name}")
|
|
325
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
326
|
+
assert is_text_visible(selenium, "Maxissimus Mustermann")
|
|
327
|
+
assert is_string_not_visible(selenium, "Max Mustermann")
|
|
328
|
+
assert is_string_not_visible(selenium, "Maike Mustermann")
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
@pytest.mark.skip(reason="no way of currently testing this")
|
|
332
|
+
@pytest.mark.django_db
|
|
333
|
+
# This test class is currently bugged because of frontend issues.
|
|
334
|
+
class TestCRMRelationShipManagement:
|
|
335
|
+
def test_create_edit_and_delete_relationship(self, live_server, selenium):
|
|
336
|
+
"""
|
|
337
|
+
Creates, edits and deletes a Customer-Employer-Relationship.
|
|
338
|
+
"""
|
|
339
|
+
user: User = create_main_company_user(USER_PASSWORD)
|
|
340
|
+
actions = ActionChains(selenium, 1000)
|
|
341
|
+
set_up(selenium, live_server, user.email, USER_PASSWORD)
|
|
342
|
+
set_up_persons()
|
|
343
|
+
|
|
344
|
+
# -----> CREATE <----- #
|
|
345
|
+
cmr = create_new_cmr_instance(selenium, ["client", "relationship_manager", "primary"], True, False)
|
|
346
|
+
open_menu_item(selenium, "Client Manager Relationships", perform_mouse_move=True)
|
|
347
|
+
cmr_element = find_element_by_text(selenium, cmr.client.computed_str)
|
|
348
|
+
|
|
349
|
+
assert is_counter_as_expected(selenium, 1)
|
|
350
|
+
assert is_text_visible(selenium, cmr.client.computed_str)
|
|
351
|
+
assert is_text_visible(selenium, cmr.relationship_manager.computed_str)
|
|
352
|
+
assert does_background_color_match(cmr_element, ClientManagerRelationshipColor.DRAFT.value)
|
|
353
|
+
|
|
354
|
+
# # -----> Edit <----- #
|
|
355
|
+
|
|
356
|
+
edit_list_instance(
|
|
357
|
+
selenium,
|
|
358
|
+
actions,
|
|
359
|
+
cmr.client.computed_str,
|
|
360
|
+
ClientManagerModelSerializer(cmr),
|
|
361
|
+
{"relationship_manager": user.profile.computed_str},
|
|
362
|
+
)
|
|
363
|
+
assert is_string_not_visible(selenium, cmr.relationship_manager.computed_str)
|
|
364
|
+
assert is_text_visible(selenium, user.profile.computed_str)
|
|
365
|
+
assert is_counter_as_expected(selenium, Person.objects.count())
|
|
366
|
+
|
|
367
|
+
# # -----> Approve <----- #
|
|
368
|
+
# TODO Implement approve
|
|
369
|
+
# -----> Delete <----- #
|
|
370
|
+
# TODO Implement delete
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from unittest.mock import patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from rest_framework.test import APIRequestFactory
|
|
5
|
+
from wbcore.contrib.authentication.factories import UserFactory
|
|
6
|
+
from wbcore.contrib.directory.factories import PersonFactory
|
|
7
|
+
from wbcore.contrib.workflow.factories import (
|
|
8
|
+
ProcessStepFactory,
|
|
9
|
+
RandomChildStepFactory,
|
|
10
|
+
UserStepFactory,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from wbcrm.workflows.assignee_methods import activity_assignee
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.django_db
|
|
17
|
+
class TestAssigneeMethods:
|
|
18
|
+
api_factory = APIRequestFactory()
|
|
19
|
+
|
|
20
|
+
def test_activity_assignee(self, activity_factory):
|
|
21
|
+
user = UserFactory()
|
|
22
|
+
activity = activity_factory(assigned_to=user.profile)
|
|
23
|
+
process_step = ProcessStepFactory(process__instance=activity)
|
|
24
|
+
assert activity_assignee(process_step) == user
|
|
25
|
+
|
|
26
|
+
@patch("wbcore.contrib.workflow.models.step.Step.set_failed")
|
|
27
|
+
def test_activity_assignee_no_activity(self, mock_failed):
|
|
28
|
+
step = RandomChildStepFactory(exclude_factories=[UserStepFactory])
|
|
29
|
+
process_step = ProcessStepFactory(step=step)
|
|
30
|
+
assert activity_assignee(process_step) is None
|
|
31
|
+
assert mock_failed.call_args.args[0] == process_step
|
|
32
|
+
|
|
33
|
+
@patch("wbcore.contrib.workflow.models.step.Step.set_failed")
|
|
34
|
+
def test_activity_assignee_no_user_account(self, mock_failed, activity_factory):
|
|
35
|
+
assignee = PersonFactory()
|
|
36
|
+
activity = activity_factory(assigned_to=assignee)
|
|
37
|
+
step = RandomChildStepFactory(exclude_factories=[UserStepFactory])
|
|
38
|
+
process_step = ProcessStepFactory(step=step, process__instance=activity)
|
|
39
|
+
assert activity_assignee(process_step) is None
|
|
40
|
+
assert mock_failed.call_args.args[0] == process_step
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from rest_framework import status
|
|
3
|
+
from rest_framework.test import APIRequestFactory
|
|
4
|
+
from wbcore.test.utils import get_kwargs
|
|
5
|
+
|
|
6
|
+
from wbcrm.factories import ActivityFactory
|
|
7
|
+
from wbcrm.viewsets import ActivityChartModelViewSet, ActivityViewSet
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.django_db
|
|
11
|
+
class TestSpecificsChartViewsets:
|
|
12
|
+
@pytest.mark.parametrize(
|
|
13
|
+
"mvs, factory",
|
|
14
|
+
[
|
|
15
|
+
(ActivityChartModelViewSet, ActivityFactory),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
18
|
+
def test_option_request(self, mvs, factory, superuser):
|
|
19
|
+
request = APIRequestFactory().options("")
|
|
20
|
+
request.user = superuser
|
|
21
|
+
factory()
|
|
22
|
+
kwargs = {"user_id": request.user.id}
|
|
23
|
+
vs = mvs.as_view({"options": "options"})
|
|
24
|
+
response = vs(request, **kwargs)
|
|
25
|
+
assert response.status_code == status.HTTP_200_OK
|
|
26
|
+
assert response.data
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize(
|
|
29
|
+
"mvs, factory",
|
|
30
|
+
[
|
|
31
|
+
(ActivityChartModelViewSet, ActivityFactory),
|
|
32
|
+
],
|
|
33
|
+
)
|
|
34
|
+
def test_viewsets(self, mvs, factory, superuser):
|
|
35
|
+
request = APIRequestFactory().get("")
|
|
36
|
+
request.user = superuser
|
|
37
|
+
factory()
|
|
38
|
+
kwargs = {"user_id": request.user.id}
|
|
39
|
+
vs = mvs.as_view({"get": "list"})
|
|
40
|
+
response = vs(request, **kwargs)
|
|
41
|
+
assert response.status_code == status.HTTP_200_OK
|
|
42
|
+
assert response.data
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.django_db
|
|
46
|
+
class TestSpecificsInfiniteViewsets:
|
|
47
|
+
@pytest.mark.parametrize(
|
|
48
|
+
"mvs, factory",
|
|
49
|
+
[
|
|
50
|
+
(
|
|
51
|
+
ActivityViewSet,
|
|
52
|
+
ActivityFactory,
|
|
53
|
+
),
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
def test_option_request(self, mvs, factory, superuser):
|
|
57
|
+
request = APIRequestFactory().options("")
|
|
58
|
+
request.user = superuser
|
|
59
|
+
obj = factory(participants=(request.user.profile,))
|
|
60
|
+
request.GET = request.GET.copy()
|
|
61
|
+
request.GET["date_gte"] = str(obj.start.date())
|
|
62
|
+
kwargs = {}
|
|
63
|
+
mvs.request = request
|
|
64
|
+
vs = mvs.as_view({"options": "options"})
|
|
65
|
+
kwargs = get_kwargs(obj, mvs, request=request)
|
|
66
|
+
response = vs(request, **kwargs).render()
|
|
67
|
+
assert response.status_code == status.HTTP_200_OK
|
|
68
|
+
assert response.data
|
|
69
|
+
|
|
70
|
+
@pytest.mark.parametrize(
|
|
71
|
+
"mvs, factory",
|
|
72
|
+
[
|
|
73
|
+
(
|
|
74
|
+
ActivityViewSet,
|
|
75
|
+
ActivityFactory,
|
|
76
|
+
),
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
def test_viewsets(self, mvs, factory, superuser):
|
|
80
|
+
request = APIRequestFactory().get("")
|
|
81
|
+
request.user = superuser
|
|
82
|
+
obj = factory(participants=(request.user.profile,))
|
|
83
|
+
request.GET = request.GET.copy()
|
|
84
|
+
request.GET["date_gte"] = str(obj.start.date())
|
|
85
|
+
kwargs = {}
|
|
86
|
+
mvs.request = request
|
|
87
|
+
vs = mvs.as_view({"get": "list"})
|
|
88
|
+
response = vs(request, **kwargs).render()
|
|
89
|
+
assert response.status_code == status.HTTP_200_OK
|
|
90
|
+
assert response.data
|
|
91
|
+
|
|
92
|
+
@pytest.mark.parametrize(
|
|
93
|
+
"mvs, factory",
|
|
94
|
+
[
|
|
95
|
+
(
|
|
96
|
+
ActivityViewSet,
|
|
97
|
+
ActivityFactory,
|
|
98
|
+
),
|
|
99
|
+
],
|
|
100
|
+
)
|
|
101
|
+
def test_viewsets_without_date_gte(self, mvs, factory, superuser):
|
|
102
|
+
request = APIRequestFactory().get("")
|
|
103
|
+
request.user = superuser
|
|
104
|
+
factory(participants=(request.user.profile,))
|
|
105
|
+
request.GET = request.GET.copy()
|
|
106
|
+
request.GET["date_gte"] = None
|
|
107
|
+
kwargs = {}
|
|
108
|
+
mvs.request = request
|
|
109
|
+
vs = mvs.as_view({"get": "list"})
|
|
110
|
+
response = vs(request, **kwargs).render()
|
|
111
|
+
assert response.status_code == status.HTTP_200_OK
|
|
112
|
+
assert response.data
|
wbcrm/tests/test_dto.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from wbcore.contrib.directory.typings import Person as PersonDTO
|
|
3
|
+
|
|
4
|
+
from wbcrm.typings import Activity as ActivityDTO
|
|
5
|
+
from wbcrm.typings import ParticipantStatus as ParticipantStatusDTO
|
|
6
|
+
from wbcrm.typings import User as UserDTO
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.django_db
|
|
10
|
+
class TestDTO:
|
|
11
|
+
@pytest.mark.parametrize("user_id", [None, 1])
|
|
12
|
+
def test_user_comparison(self, user_id):
|
|
13
|
+
user1 = UserDTO(1, {})
|
|
14
|
+
user2 = UserDTO(id=user_id, metadata={})
|
|
15
|
+
if user1.id == user2.id is not None:
|
|
16
|
+
assert user1 == user2
|
|
17
|
+
else:
|
|
18
|
+
assert user1 != user2
|
|
19
|
+
assert user2 is not None
|
|
20
|
+
|
|
21
|
+
@pytest.mark.parametrize(
|
|
22
|
+
"id, name, email",
|
|
23
|
+
[
|
|
24
|
+
(None, None, None),
|
|
25
|
+
(None, "test", None),
|
|
26
|
+
(None, "test", "test@test.com"),
|
|
27
|
+
(1, None, None),
|
|
28
|
+
(1, "test", None),
|
|
29
|
+
(1, "test", "test@test.com"),
|
|
30
|
+
],
|
|
31
|
+
)
|
|
32
|
+
def test_participation_status(self, id, name, email):
|
|
33
|
+
person1 = PersonDTO(1, "test", "test", "test@test.com")
|
|
34
|
+
person2 = PersonDTO(id=id, first_name=name, last_name=name, email=email)
|
|
35
|
+
|
|
36
|
+
participant1 = ParticipantStatusDTO(person=person1)
|
|
37
|
+
participant2 = ParticipantStatusDTO(person=person2)
|
|
38
|
+
if (participant1.id == participant2.id is not None) or (
|
|
39
|
+
participant1.person == participant2.person and participant1.activity == participant2.activity
|
|
40
|
+
):
|
|
41
|
+
assert participant1 == participant2
|
|
42
|
+
else:
|
|
43
|
+
assert participant1 != participant2
|
|
44
|
+
assert participant2 is not None
|
|
45
|
+
|
|
46
|
+
@pytest.mark.parametrize(
|
|
47
|
+
"id, title, email",
|
|
48
|
+
[
|
|
49
|
+
(None, None, None),
|
|
50
|
+
(None, "test", None),
|
|
51
|
+
(None, "test", "test@test.com"),
|
|
52
|
+
(1, None, None),
|
|
53
|
+
(1, "test", None),
|
|
54
|
+
(1, "test", "test@test.com"),
|
|
55
|
+
],
|
|
56
|
+
)
|
|
57
|
+
def test_activity(self, id, title, email):
|
|
58
|
+
activity1 = ActivityDTO(id=1, title="test", metadata={})
|
|
59
|
+
activity2 = ActivityDTO(id=id, title=title, metadata={})
|
|
60
|
+
if activity1.id == activity2.id is not None:
|
|
61
|
+
assert activity1 == activity2
|
|
62
|
+
else:
|
|
63
|
+
assert activity1 != activity2
|
|
64
|
+
assert activity2 is not None
|