wbintegrator_office365 1.43.1__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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
+ ]