wbintegrator_office365 1.43.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. wbintegrator_office365/__init__.py +1 -0
  2. wbintegrator_office365/admin.py +209 -0
  3. wbintegrator_office365/apps.py +5 -0
  4. wbintegrator_office365/configurations/__init__.py +0 -0
  5. wbintegrator_office365/configurations/configurations/__init__.py +23 -0
  6. wbintegrator_office365/dynamic_preferences_registry.py +15 -0
  7. wbintegrator_office365/factories.py +102 -0
  8. wbintegrator_office365/filters.py +237 -0
  9. wbintegrator_office365/importer/__init__.py +3 -0
  10. wbintegrator_office365/importer/api.py +403 -0
  11. wbintegrator_office365/importer/disable_signals.py +43 -0
  12. wbintegrator_office365/importer/parser.py +135 -0
  13. wbintegrator_office365/kpi_handlers/__init__.py +1 -0
  14. wbintegrator_office365/kpi_handlers/calls.py +114 -0
  15. wbintegrator_office365/migrations/0001_initial_squashed_squashed_0003_alter_calendar_owner_alter_calendarevent_organizer_and_more.py +677 -0
  16. wbintegrator_office365/migrations/0002_remove_calendar_owner_remove_calendarevent_activity_and_more.py +85 -0
  17. wbintegrator_office365/migrations/0003_alter_event_options.py +20 -0
  18. wbintegrator_office365/migrations/__init__.py +0 -0
  19. wbintegrator_office365/models/__init__.py +3 -0
  20. wbintegrator_office365/models/event.py +623 -0
  21. wbintegrator_office365/models/subscription.py +144 -0
  22. wbintegrator_office365/models/tenant.py +62 -0
  23. wbintegrator_office365/serializers.py +266 -0
  24. wbintegrator_office365/tasks.py +108 -0
  25. wbintegrator_office365/templates/admin/tenant_change_list.html +12 -0
  26. wbintegrator_office365/tests/__init__.py +0 -0
  27. wbintegrator_office365/tests/conftest.py +28 -0
  28. wbintegrator_office365/tests/test_admin.py +86 -0
  29. wbintegrator_office365/tests/test_models.py +65 -0
  30. wbintegrator_office365/tests/test_tasks.py +318 -0
  31. wbintegrator_office365/tests/test_views.py +128 -0
  32. wbintegrator_office365/tests/tests.py +12 -0
  33. wbintegrator_office365/urls.py +46 -0
  34. wbintegrator_office365/viewsets/__init__.py +31 -0
  35. wbintegrator_office365/viewsets/display.py +306 -0
  36. wbintegrator_office365/viewsets/endpoints.py +52 -0
  37. wbintegrator_office365/viewsets/menu.py +65 -0
  38. wbintegrator_office365/viewsets/titles.py +49 -0
  39. wbintegrator_office365/viewsets/viewsets.py +745 -0
  40. wbintegrator_office365-1.43.1.dist-info/METADATA +10 -0
  41. wbintegrator_office365-1.43.1.dist-info/RECORD +42 -0
  42. wbintegrator_office365-1.43.1.dist-info/WHEEL +5 -0
@@ -0,0 +1,86 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+ from django.contrib.admin import AdminSite
5
+ from django.contrib.messages import get_messages, storage
6
+ from rest_framework import status
7
+ from rest_framework.test import APIRequestFactory
8
+ from wbcore.test.utils import get_or_create_superuser
9
+ from wbintegrator_office365.admin import SubscriptionAdmin, TenantUserAdmin
10
+ from wbintegrator_office365.factories import TenantUserFactory
11
+ from wbintegrator_office365.models import Subscription, TenantUser
12
+
13
+
14
+ @pytest.mark.django_db
15
+ class TestAdmin:
16
+ @pytest.fixture()
17
+ def fixture_request(self):
18
+ request = APIRequestFactory().get("")
19
+ request.session = {} # for sessions middleware
20
+ request._messages = storage.default_storage(request) # for messages middleware
21
+ request.user = get_or_create_superuser()
22
+ return request
23
+
24
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI._get_access_token")
25
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
26
+ def test_admin_fetch_tenantusers(self, mock_users, mock_access_token, fixture_request):
27
+ data = [
28
+ {
29
+ "id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
30
+ "display_name": "contoso1",
31
+ "email": "contoso1_gmail.com#EXT#@microsoft.onmicrosoft.com",
32
+ }
33
+ ]
34
+ mock_users.return_value.status_code = status.HTTP_200_OK
35
+ mock_users.return_value = data
36
+
37
+ mock_access_token.return_value.status_code = status.HTTP_200_OK
38
+ mock_access_token.return_value = "FAKE_TOKEN"
39
+
40
+ TenantUserFactory()
41
+ mma = TenantUserAdmin(TenantUser, AdminSite())
42
+
43
+ storages = get_messages(fixture_request)
44
+ assert len(storages) == 0
45
+
46
+ response = mma._fetch_tenantusers(fixture_request)
47
+
48
+ storages = get_messages(fixture_request)
49
+ assert len(storages) == 1
50
+ assert mock_users.call_count == 1
51
+ assert response.status_code == status.HTTP_302_FOUND
52
+
53
+ def test_disable_selected_subscriptions(self, subscription_factory, fixture_request):
54
+ obj = subscription_factory()
55
+ mma = SubscriptionAdmin(TenantUser, AdminSite())
56
+ storages = get_messages(fixture_request)
57
+ assert len(storages) == 0
58
+ assert obj.is_enable is True
59
+ mma.disable_selected_subscriptions(fixture_request, Subscription.objects.all())
60
+ obj.refresh_from_db()
61
+ assert obj.is_enable is False
62
+
63
+ storages = get_messages(fixture_request)
64
+ assert len(storages) == 1
65
+
66
+ def test_verification_selected_subscriptions(self, subscription_factory, fixture_request):
67
+ obj = subscription_factory()
68
+ mma = SubscriptionAdmin(TenantUser, AdminSite())
69
+ storages = get_messages(fixture_request)
70
+ assert len(storages) == 0
71
+ assert obj.is_enable is True
72
+ mma.verification_selected_subscriptions(fixture_request, Subscription.objects.all())
73
+
74
+ storages = get_messages(fixture_request)
75
+ assert len(storages) == 1
76
+
77
+ def test_renew_selected_subscriptions(self, subscription_factory, fixture_request):
78
+ obj = subscription_factory()
79
+ mma = SubscriptionAdmin(TenantUser, AdminSite())
80
+ storages = get_messages(fixture_request)
81
+ assert len(storages) == 0
82
+ assert obj.is_enable is True
83
+ mma.renew_selected_subscriptions(fixture_request, Subscription.objects.all())
84
+
85
+ storages = get_messages(fixture_request)
86
+ assert len(storages) == 1
@@ -0,0 +1,65 @@
1
+ from unittest.mock import patch
2
+
3
+ import pytest
4
+ from wbintegrator_office365.factories import EventFactory, SubscriptionFactory
5
+ from wbintegrator_office365.importer import DisableSignals
6
+ from wbintegrator_office365.models import (
7
+ CallEvent,
8
+ CallUser,
9
+ Event,
10
+ Subscription,
11
+ TenantUser,
12
+ )
13
+
14
+
15
+ @pytest.mark.django_db
16
+ class TestModels:
17
+ def test_tenantuser(self, tenant_user_factory):
18
+ assert TenantUser.objects.count() == 0
19
+ tenant_user_factory()
20
+ assert TenantUser.objects.count() == 1
21
+
22
+ def test_event(self, event_factory):
23
+ assert Event.objects.count() == 0
24
+ # obj = event_factory() # there is a confusion with another model event from another app
25
+ EventFactory()
26
+ assert Event.objects.count() == 1
27
+
28
+ @patch("wbintegrator_office365.models.subscription.unsubscribe.delay")
29
+ @patch("wbintegrator_office365.models.subscription.chain")
30
+ @patch("requests.post")
31
+ def test_subscription(self, mock_post, mock_chain, mock_unsubscribe):
32
+ with patch("wbintegrator_office365.models.event.transaction.on_commit", new=lambda fn: fn()):
33
+ assert Subscription.objects.count() == 0
34
+ assert mock_chain.call_count == 0
35
+ SubscriptionFactory()
36
+ assert Subscription.objects.count() == 1
37
+ assert mock_chain.call_count == 0
38
+
39
+ assert mock_unsubscribe.call_count == 0
40
+ SubscriptionFactory(is_enable=False)
41
+ assert mock_chain.call_count == 1
42
+
43
+ def test_call_event_disconnect_signal(self, call_event_factory):
44
+ assert CallEvent.objects.count() == 0
45
+ with DisableSignals():
46
+ call_event_factory()
47
+ assert CallEvent.objects.count() == 1
48
+
49
+ def test_call_event(self, call_event_factory):
50
+ assert CallEvent.objects.count() == 0
51
+ call_event_factory()
52
+ assert CallEvent.objects.count() == 1
53
+
54
+ def test_call_user(self, call_user_factory):
55
+ assert CallUser.objects.count() == 0
56
+ call_user_factory()
57
+ assert CallUser.objects.count() == 1
58
+
59
+ def test_post_save_participant_event(self, call_event_factory, call_user_factory):
60
+ obj = call_event_factory()
61
+ call_user = call_user_factory()
62
+ obj.participants.add(call_user)
63
+ assert obj.is_internal_call is False
64
+ obj.participants.remove(call_user)
65
+ assert obj.is_internal_call is True
@@ -0,0 +1,318 @@
1
+ from datetime import timedelta
2
+ from unittest.mock import patch
3
+
4
+ import pandas as pd
5
+ import phonenumbers
6
+ import pytest
7
+ from rest_framework import status
8
+ from wbcore.contrib.directory.factories import TelephoneContactFactory
9
+ from wbintegrator_office365.factories import SubscriptionFactory, TenantUserFactory
10
+ from wbintegrator_office365.importer import parse
11
+ from wbintegrator_office365.models import CallEvent, Subscription
12
+ from wbintegrator_office365.models.event import fetch_tenantusers
13
+ from wbintegrator_office365.models.subscription import (
14
+ subscribe,
15
+ unsubscribe,
16
+ verification_subscriptions,
17
+ )
18
+
19
+
20
+ # This method will be used by the mock to replace requests.get
21
+ class MockResponse:
22
+ def __init__(self, json_data, status_code):
23
+ self.json_data = json_data
24
+ self.status_code = status_code
25
+
26
+ def json(self):
27
+ return self.json_data
28
+
29
+
30
+ @pytest.mark.django_db
31
+ class TestTaskSubscription:
32
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI._get_access_token")
33
+ @patch("wbintegrator_office365.importer.api.requests.post")
34
+ def test_subscribe(self, mock_post, mock_access_token):
35
+ obj = SubscriptionFactory(type_resource=Subscription.TypeResource.CALLRECORD)
36
+ data = {
37
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#subscriptions/$entity",
38
+ "value": [
39
+ {
40
+ "id": "7f105c7d-2dc5-4530-97cd-4e7ae6534c07",
41
+ "resource": "me/mailFolders('Inbox')/messages",
42
+ "applicationId": "24d3b144-21ae-4080-943f-7067b395b913",
43
+ "changeType": "created",
44
+ "clientState": "secretClientValue",
45
+ "notificationUrl": "https://webhook.azurewebsites.net/api/send/myNotifyClient",
46
+ "expirationDateTime": "2016-11-20T18:23:45.9356913Z",
47
+ "creatorId": "8ee44408-0679-472c-bc2a-692812af3437",
48
+ "latestSupportedTlsVersion": "v1_2",
49
+ }
50
+ ],
51
+ }
52
+ data = parse(pd.json_normalize(data.get("value")))[0]
53
+ mock_access_token.return_value.status_code = status.HTTP_200_OK
54
+ mock_access_token.return_value = "FAKE_TOKEN"
55
+
56
+ mock_post.return_value = MockResponse(data, 201)
57
+ assert obj.subscription_id != data.get("id")
58
+ subscribe(obj.id, "/communications/callRecords")
59
+ assert mock_post.call_count == 1
60
+ obj = Subscription.objects.get(id=obj.id)
61
+ assert obj.subscription_id == data.get("id")
62
+
63
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
64
+ @patch("wbintegrator_office365.models.subscription.chain")
65
+ def test_post_save_subscription(self, mock_chain, mock_users):
66
+ with patch("wbintegrator_office365.models.event.transaction.on_commit", new=lambda fn: fn()):
67
+ mock_chain.return_value.status_code = 200
68
+ mock_users.return_value.status_code = 200
69
+
70
+ tenant = TenantUserFactory()
71
+ mock_users.return_value = [{"id": tenant.tenant_id}]
72
+
73
+ assert mock_chain.call_count == 0
74
+ SubscriptionFactory(
75
+ is_enable=True, type_resource=Subscription.TypeResource.CALLRECORD, expiration_date=None
76
+ )
77
+ assert mock_chain.call_count == 1
78
+ SubscriptionFactory(
79
+ subscription_id=None,
80
+ is_enable=True,
81
+ tenant_user=tenant,
82
+ type_resource=Subscription.TypeResource.CALENDAR,
83
+ )
84
+ assert mock_chain.call_count == 1
85
+
86
+ @pytest.mark.parametrize("type_resource", ["CALLRECORD", "CALENDAR"])
87
+ @patch("wbintegrator_office365.models.subscription.chain")
88
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
89
+ @patch("requests.patch")
90
+ def test_resubscribe(self, mock_patch, mock_users, mock_chain, type_resource):
91
+ if type_resource == Subscription.TypeResource.CALLRECORD:
92
+ obj = SubscriptionFactory(is_enable=True, type_resource=Subscription.TypeResource.CALLRECORD)
93
+ else:
94
+ mock_users.return_value.status_code = 200
95
+ tenant = TenantUserFactory()
96
+ mock_users.return_value = [{"id": tenant.tenant_id}]
97
+ obj = SubscriptionFactory(
98
+ is_enable=True, tenant_user=tenant, type_resource=Subscription.TypeResource.CALENDAR
99
+ )
100
+ data = {"expiration": obj.expiration_date + timedelta(days=2), "notification_url": "fake_url"}
101
+ mock_patch.return_value.status_code = 200
102
+ mock_patch.return_value.json.return_value = data
103
+
104
+ assert mock_patch.call_count == 0
105
+ obj.resubscribe()
106
+ assert mock_patch.call_count == 1
107
+
108
+ obj = Subscription.objects.get(id=obj.id)
109
+ assert obj.expiration_date == data.get("expiration")
110
+
111
+ @patch("wbintegrator_office365.models.subscription.chain")
112
+ @patch("requests.get")
113
+ def test_verification_subscriptions(self, mock_get, mock_chain):
114
+ with patch("wbintegrator_office365.models.event.transaction.on_commit", new=lambda fn: fn()):
115
+ data = {"value": [{"id": "fake_id"}]}
116
+ mock_get.return_value.status_code = 200
117
+ mock_get.return_value.json.return_value = data
118
+
119
+ obj = SubscriptionFactory(
120
+ expiration_date=None, type_resource="CALLRECORD", is_enable=True, subscription_id="fake_id"
121
+ )
122
+ obj2 = SubscriptionFactory(
123
+ subscription_id=None, type_resource="CALENDAR", is_enable=True, tenant_user=TenantUserFactory()
124
+ )
125
+ obj2.subscription_id = "other_fake_id"
126
+ obj2.save()
127
+
128
+ assert mock_chain.call_count == 1
129
+ assert mock_get.call_count == 0
130
+ verification_subscriptions(obj.id)
131
+ assert mock_get.call_count == 1
132
+ verification_subscriptions(obj2.id)
133
+ assert mock_get.call_count == 2
134
+
135
+ assert Subscription.objects.get(id=obj.id).is_enable is True
136
+ assert Subscription.objects.get(id=obj2.id).is_enable is False
137
+
138
+ @patch("requests.delete")
139
+ def test_unsubscribe(self, mock_delete):
140
+ mock_delete.return_value.status_code = 204
141
+ obj = SubscriptionFactory(is_enable=True)
142
+ assert mock_delete.call_count == 0
143
+ unsubscribe(obj.id)
144
+ assert mock_delete.call_count == 1
145
+
146
+
147
+ data = {
148
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords/$entity",
149
+ "version": 1,
150
+ "type": "peerToPeer",
151
+ "modalities": ["audio"],
152
+ "lastModifiedDateTime": "2020-02-25T19:00:24.582757Z",
153
+ "startDateTime": "2020-02-25T18:52:21.2169889Z",
154
+ "endDateTime": "2020-02-25T18:52:46.7640013Z",
155
+ "id": "e523d2ed-2966-4b6b-925b-754a88034cc5",
156
+ "organizer": {
157
+ "user": {
158
+ "id": "821809f5-0000-0000-0000-3b5136c0e777",
159
+ "displayName": "Abbie Wilkins",
160
+ "tenantId": "dc368399-474c-4d40-900c-6265431fd81f",
161
+ }
162
+ },
163
+ "participants": [
164
+ {
165
+ "user": {
166
+ "id": "821809f5-0000-0000-0000-3b5136c0e777",
167
+ "displayName": "Abbie Wilkins",
168
+ "tenantId": "dc368399-474c-4d40-900c-6265431fd81f",
169
+ }
170
+ },
171
+ {
172
+ "user": {
173
+ "id": "f69e2c00-0000-0000-0000-185e5f5f5d8a",
174
+ "displayName": "Owen Franklin",
175
+ "tenantId": "dc368399-474c-4d40-900c-6265431fd81f",
176
+ }
177
+ },
178
+ ],
179
+ }
180
+
181
+ data_with_guest_user = {
182
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords/$entity",
183
+ "version": 1,
184
+ "type": "peerToPeer",
185
+ "modalities": ["audio"],
186
+ "lastModifiedDateTime": "2020-02-25T19:00:24.582757Z",
187
+ "startDateTime": "2020-02-25T18:52:21.2169889Z",
188
+ "endDateTime": "2020-02-25T18:52:46.7640013Z",
189
+ "id": "e523d2ed-2966-4b6b-925b-754a88034cc5",
190
+ "organizer": {
191
+ "user": {
192
+ "id": "821809f5-0000-0000-0000-3b5136c0e777",
193
+ "displayName": "Abbie Wilkins",
194
+ "tenantId": "dc368399-474c-4d40-900c-6265431fd81f",
195
+ }
196
+ },
197
+ "participants": [
198
+ {
199
+ "user": None,
200
+ "acsUser": None,
201
+ "spoolUser": None,
202
+ "phone": None,
203
+ "guest": {"id": "c6f4f18f1e99401a9193fbf954f6e903", "displayName": "Guest user", "tenantId": None},
204
+ "encrypted": None,
205
+ "onPremises": None,
206
+ "acsApplicationInstance": None,
207
+ "spoolApplicationInstance": None,
208
+ "applicationInstance": None,
209
+ "application": None,
210
+ "device": None,
211
+ },
212
+ {
213
+ "acsUser": None,
214
+ "spoolUser": None,
215
+ "phone": None,
216
+ "guest": None,
217
+ "encrypted": None,
218
+ "onPremises": None,
219
+ "acsApplicationInstance": None,
220
+ "spoolApplicationInstance": None,
221
+ "applicationInstance": None,
222
+ "application": None,
223
+ "device": None,
224
+ "user": {
225
+ "id": "303eecac-5bf1-44df-96c2-2aae187d46d1",
226
+ "displayName": "External user",
227
+ "tenantId": "9692a3d3-2a08-4ec8-a0bd-1db355eb4230",
228
+ },
229
+ },
230
+ ],
231
+ }
232
+
233
+ data_with_guest_organiser = {
234
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords/$entity",
235
+ "version": 1,
236
+ "type": "peerToPeer",
237
+ "modalities": ["audio"],
238
+ "lastModifiedDateTime": "2020-02-25T19:00:24.582757Z",
239
+ "startDateTime": "2020-02-25T18:52:21.2169889Z",
240
+ "endDateTime": "2020-02-25T18:52:46.7640013Z",
241
+ "id": "e523d2ed-2966-4b6b-925b-754a88034cc5",
242
+ "organizer": {
243
+ "user": None,
244
+ "guest": {
245
+ "id": "821809f5-0000-0000-0000-3b5136c0e777",
246
+ "displayName": "Abbie Wilkins",
247
+ "tenantId": "dc368399-474c-4d40-900c-6265431fd81f",
248
+ },
249
+ },
250
+ "participants": [],
251
+ }
252
+
253
+ data_with_phone_organiser = {
254
+ "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords/$entity",
255
+ "version": 1,
256
+ "type": "peerToPeer",
257
+ "modalities": ["audio"],
258
+ "lastModifiedDateTime": "2020-02-25T19:00:24.582757Z",
259
+ "startDateTime": "2020-02-25T18:52:21.2169889Z",
260
+ "endDateTime": "2020-02-25T18:52:46.7640013Z",
261
+ "id": "e523d2ed-2966-4b6b-925b-754a88034cc5",
262
+ "organizer": {
263
+ "user": None,
264
+ "guest": None,
265
+ "phone": {"id": "+41223178146", "displayName": "None", "tenantId": "None"},
266
+ },
267
+ "participants": [],
268
+ }
269
+
270
+
271
+ @pytest.mark.django_db
272
+ class TestTasksCall:
273
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
274
+ def test_fetch_tenantusers(self, mock_users):
275
+ data = [
276
+ {
277
+ "id": "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
278
+ "display_name": "contoso1",
279
+ "email": "contoso1_gmail.com#EXT#@microsoft.onmicrosoft.com",
280
+ }
281
+ ]
282
+ mock_users.return_value.status_code = 200
283
+ mock_users.return_value = data
284
+ datum, count_added = fetch_tenantusers()
285
+ assert mock_users.call_count == 1
286
+ assert datum == data
287
+ assert count_added == 1
288
+
289
+ @patch("requests.get")
290
+ @pytest.mark.parametrize(
291
+ "data", [data, data_with_guest_user, data_with_guest_organiser, data_with_phone_organiser]
292
+ )
293
+ def test_fetch_call(self, mock_get, data, event_factory):
294
+ event = event_factory(uuid_event="87d349ed-44d7-43e1-9a83-5f2406dee5bd")
295
+ mock_get.return_value.status_code = 200
296
+ mock_get.return_value.json.return_value = parse(pd.json_normalize(data))
297
+
298
+ assert CallEvent.objects.count() == 0
299
+ event.fetch_call()
300
+ assert mock_get.call_count == 1
301
+ assert CallEvent.objects.count() == 1
302
+
303
+ @patch("requests.get")
304
+ @pytest.mark.parametrize("data", [data_with_phone_organiser])
305
+ def test_fetch_call_phone(self, mock_get, data, event_factory):
306
+ event = event_factory(uuid_event="87d349ed-44d7-43e1-9a83-5f2406dee5bd")
307
+ mock_get.return_value.status_code = 200
308
+ mock_get.return_value.json.return_value = parse(pd.json_normalize(data))
309
+
310
+ my_number = "+41 22 317 81 46"
311
+ parser_number = phonenumbers.parse(my_number, "CH")
312
+ phone_numbers = phonenumbers.format_number(parser_number, phonenumbers.PhoneNumberFormat.E164)
313
+ TelephoneContactFactory(number=phone_numbers)
314
+
315
+ assert CallEvent.objects.count() == 0
316
+ event.fetch_call()
317
+ assert mock_get.call_count == 1
318
+ assert CallEvent.objects.count() == 1
@@ -0,0 +1,128 @@
1
+ from datetime import timedelta
2
+ from unittest.mock import patch
3
+
4
+ import pytest
5
+ from rest_framework import status
6
+ from rest_framework.test import APIRequestFactory
7
+ from wbcore.contrib.authentication.factories import InternalUserFactory
8
+ from wbcore.test.utils import get_or_create_superuser
9
+ from wbhuman_resources.factories import EmployeeHumanResourceFactory
10
+ from wbintegrator_office365.factories import CallEventFactory, CallUserFactory
11
+ from wbintegrator_office365.viewsets.viewsets import (
12
+ CallEventReceptionTime,
13
+ CallEventSummaryGraph,
14
+ callback_consent_permission,
15
+ listen,
16
+ )
17
+
18
+
19
+ @pytest.mark.django_db
20
+ class TestView:
21
+ @pytest.mark.parametrize(
22
+ "mvs, factory",
23
+ [
24
+ (CallEventReceptionTime, CallEventFactory),
25
+ (CallEventSummaryGraph, CallEventFactory),
26
+ ],
27
+ )
28
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI._get_access_token")
29
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
30
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.get_calendar_event")
31
+ def test_option_request(self, mock_calendar_event, mock_users, mock_acess, mvs, factory):
32
+ request = APIRequestFactory().options("")
33
+ request.user = get_or_create_superuser()
34
+ factory()
35
+ kwargs = {"user_id": request.user.id}
36
+ vs = mvs.as_view({"options": "options"})
37
+ response = vs(request, **kwargs)
38
+ assert response.status_code == status.HTTP_200_OK
39
+ assert response.data
40
+
41
+ @pytest.mark.parametrize(
42
+ "mvs, factory",
43
+ [
44
+ (CallEventReceptionTime, CallEventFactory),
45
+ (CallEventSummaryGraph, CallEventFactory),
46
+ ],
47
+ )
48
+ def test_get_plotly(self, mvs, factory):
49
+ request = APIRequestFactory().get("")
50
+ request.user = get_or_create_superuser()
51
+ _mvs = mvs(request=request)
52
+ fig = _mvs.get_plotly(_mvs.queryset)
53
+ assert fig
54
+
55
+ factory()
56
+ _mvs = mvs(request=request)
57
+ fig = _mvs.get_plotly(_mvs.queryset)
58
+ assert fig
59
+
60
+ @pytest.mark.parametrize(
61
+ "mvs, factory, empty_compare_employee",
62
+ [(CallEventSummaryGraph, CallEventFactory, True), (CallEventSummaryGraph, CallEventFactory, False)],
63
+ )
64
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI._get_access_token")
65
+ @patch("wbintegrator_office365.importer.MicrosoftGraphAPI.users")
66
+ def test_get_plotly_CallEventSummaryGraph(self, mock_users, mock_acess, mvs, factory, empty_compare_employee):
67
+ request = APIRequestFactory().get("")
68
+ request.user = get_or_create_superuser()
69
+
70
+ obj = factory(is_internal_call=True)
71
+ obj.end = obj.start + timedelta(seconds=60)
72
+ person = InternalUserFactory().profile
73
+ employee = EmployeeHumanResourceFactory(profile=person)
74
+
75
+ if not empty_compare_employee:
76
+ call_user = CallUserFactory(tenant_user__profile=person)
77
+ factory(start=obj.start, end=obj.end, type=obj.type, is_internal_call=True, participants=(call_user,))
78
+
79
+ request.GET = request.GET.copy()
80
+ request.GET["compare_employee"] = employee.id
81
+ request.GET["start"] = str(obj.start.date())
82
+ request.GET["end"] = str(obj.end.date() + timedelta(days=30))
83
+ request.GET["call_duration"] = (obj.end - obj.start).total_seconds()
84
+ request.GET["call_type"] = obj.type
85
+ request.GET["call_area"] = obj.is_internal_call
86
+ request.GET["business_day_without_call"] = "true"
87
+ _mvs = mvs(request=request)
88
+ fig = _mvs.get_plotly(_mvs.get_queryset())
89
+ assert fig
90
+
91
+ @pytest.mark.parametrize("view", [callback_consent_permission])
92
+ def test_callback_consent_permission(self, view):
93
+ factory = APIRequestFactory()
94
+ request = factory.get("")
95
+ response = view(request)
96
+ assert response.status_code == status.HTTP_200_OK
97
+
98
+ data = {
99
+ "value": [
100
+ {
101
+ "change_type": "created",
102
+ "subscription_id": "82507f73-75c5-4295-8ac4-5bf55f38541f",
103
+ "resource": "communications/callRecords/af419444-a189-499c-967b-1aae574b2cc1",
104
+ "resource_data": {"id": "af419444-a189-499c-967b-1aae574b2cc1"},
105
+ }
106
+ ]
107
+ }
108
+
109
+ @patch("wbintegrator_office365.models.event.handle_event_from_webhook.delay")
110
+ @pytest.mark.parametrize(
111
+ "view, validation_token, request_body",
112
+ [(listen, None, None), (listen, "validationToken", None), (listen, None, data)],
113
+ )
114
+ def test_listen(self, handle_event, view, validation_token, request_body, event_factory):
115
+ with patch("wbintegrator_office365.viewsets.viewsets.transaction.on_commit", new=lambda fn: fn()):
116
+ factory = APIRequestFactory()
117
+ request = factory.post("", request_body, format="json")
118
+ if validation_token:
119
+ request.GET = request.GET.copy()
120
+ request.GET["validationToken"] = "fake_validation_token"
121
+ assert handle_event.call_count == 0
122
+ for i in range(1, 3):
123
+ response = view(request)
124
+ if request_body:
125
+ assert handle_event.call_count == i
126
+ else:
127
+ assert handle_event.call_count == 0
128
+ assert response.status_code == status.HTTP_200_OK
@@ -0,0 +1,12 @@
1
+ import pytest
2
+ from wbcore.test import GenerateTest, default_config
3
+
4
+ config = {}
5
+ for key, value in default_config.items():
6
+ config[key] = list(filter(lambda x: x.__module__.startswith("wbintegrator_office365"), value))
7
+
8
+
9
+ @pytest.mark.django_db
10
+ @GenerateTest(config)
11
+ class TestProject:
12
+ pass
@@ -0,0 +1,46 @@
1
+ from django.urls import include, path
2
+ from wbcore.routers import WBCoreRouter
3
+ from wbintegrator_office365.viewsets import viewsets
4
+
5
+ router = WBCoreRouter()
6
+ router.register(
7
+ r"tenantuserrepresentation", viewsets.TenantUserRepresentationViewSet, basename="tenantuserrepresentation"
8
+ )
9
+ router.register(r"tenantuser", viewsets.TenantUserViewSet)
10
+
11
+ router.register(
12
+ r"subscriptionrepresentation", viewsets.SubscriptionRepresentationViewSet, basename="subscriptionrepresentation"
13
+ )
14
+ router.register(r"subscription", viewsets.SubscriptionViewSet, basename="subscription")
15
+
16
+ router.register(r"eventrepresentation", viewsets.EventRepresentationViewSet, basename="eventrepresentation")
17
+ router.register(r"event", viewsets.EventViewSet, basename="event")
18
+
19
+ router.register(r"calluserrepresentation", viewsets.CallUserRepresentationViewSet, basename="calluserrepresentation")
20
+ router.register(r"calluser", viewsets.CallUserViewSet, basename="calluser")
21
+
22
+ router.register(
23
+ r"calleventrepresentation", viewsets.CallEventRepresentationViewSet, basename="calleventrepresentation"
24
+ )
25
+ router.register(r"callevent", viewsets.CallEventViewSet, basename="callevent")
26
+
27
+ router.register(r"calleventchart", viewsets.CallEventReceptionTime, basename="calleventchart")
28
+ router.register(r"calleventsummarygraph", viewsets.CallEventSummaryGraph, basename="calleventsummarygraph")
29
+
30
+ router.register(r"eventlog", viewsets.EventLogViewSet, basename="eventlog")
31
+ router.register(r"eventlog", viewsets.EventLogRepresentationViewSet, basename="eventlogrepresentation")
32
+
33
+ event_router = WBCoreRouter()
34
+ event_router.register(
35
+ r"eventlog",
36
+ viewsets.EventLogEventViewSet,
37
+ basename="event-eventlog",
38
+ )
39
+
40
+
41
+ urlpatterns = [
42
+ path("", include(router.urls)),
43
+ path("event/<str:last_event_id>/", include(event_router.urls)),
44
+ path("listen", viewsets.listen, name="listen"),
45
+ path("callback/permissions", viewsets.callback_consent_permission),
46
+ ]