138 lines
5.8 KiB
Python
138 lines
5.8 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
from collections import defaultdict
|
||
|
from datetime import datetime
|
||
|
from unittest.mock import patch
|
||
|
|
||
|
from odoo.addons.google_calendar.utils.google_calendar import GoogleCalendarService
|
||
|
from odoo.addons.google_account.models.google_service import GoogleService
|
||
|
from odoo.addons.google_calendar.models.res_users import User
|
||
|
from odoo.addons.google_calendar.models.google_sync import google_calendar_token, GoogleSync
|
||
|
from odoo.tests.common import HttpCase, new_test_user
|
||
|
from freezegun import freeze_time
|
||
|
from contextlib import contextmanager
|
||
|
|
||
|
|
||
|
def patch_api(func):
|
||
|
def patched(self, *args, **kwargs):
|
||
|
with self.mock_google_sync():
|
||
|
return func(self, *args, **kwargs)
|
||
|
return patched
|
||
|
|
||
|
@patch.object(User, '_get_google_calendar_token', lambda user: 'dummy-token')
|
||
|
class TestSyncGoogle(HttpCase):
|
||
|
|
||
|
def setUp(self):
|
||
|
super().setUp()
|
||
|
self.google_service = GoogleCalendarService(self.env['google.service'])
|
||
|
self.env.user.sudo().unpause_google_synchronization()
|
||
|
self.organizer_user = new_test_user(self.env, login="organizer_user")
|
||
|
self.attendee_user = new_test_user(self.env, login='attendee_user')
|
||
|
|
||
|
@contextmanager
|
||
|
def mock_datetime_and_now(self, mock_dt):
|
||
|
"""
|
||
|
Used when synchronization date (using env.cr.now()) is important
|
||
|
in addition to standard datetime mocks. Used mainly to detect sync
|
||
|
issues.
|
||
|
"""
|
||
|
with freeze_time(mock_dt), \
|
||
|
patch.object(self.env.cr, 'now', lambda: mock_dt):
|
||
|
yield
|
||
|
|
||
|
@contextmanager
|
||
|
def mock_google_sync(self, user_id=None):
|
||
|
self._gsync_deleted_ids = []
|
||
|
self._gsync_insert_values = []
|
||
|
self._gsync_patch_values = defaultdict(list)
|
||
|
|
||
|
# as these are normally post-commit hooks, we don't change any state here
|
||
|
def _mock_delete(model, service, google_id, **kwargs):
|
||
|
with google_calendar_token(user_id or model.env.user.sudo()) as token:
|
||
|
if token:
|
||
|
self._gsync_deleted_ids.append(google_id)
|
||
|
|
||
|
def _mock_insert(model, service, values, **kwargs):
|
||
|
if not values:
|
||
|
return
|
||
|
with google_calendar_token(user_id or model.env.user.sudo()) as token:
|
||
|
if token:
|
||
|
self._gsync_insert_values.append((values, kwargs))
|
||
|
|
||
|
def _mock_patch(model, service, google_id, values, **kwargs):
|
||
|
with google_calendar_token(user_id or model.env.user.sudo()) as token:
|
||
|
if token:
|
||
|
self._gsync_patch_values[google_id].append((values, kwargs))
|
||
|
|
||
|
with self.env.cr.savepoint(), \
|
||
|
patch.object(GoogleSync, '_google_insert', autospec=True, wraps=GoogleSync, side_effect=_mock_insert), \
|
||
|
patch.object(GoogleSync, '_google_delete', autospec=True, wraps=GoogleSync, side_effect=_mock_delete), \
|
||
|
patch.object(GoogleSync, '_google_patch', autospec=True, wraps=GoogleSync, side_effect=_mock_patch):
|
||
|
yield
|
||
|
|
||
|
@contextmanager
|
||
|
def mock_google_service(self):
|
||
|
self._gservice_request_uris = []
|
||
|
|
||
|
def _mock_do_request(model, uri, *args, **kwargs):
|
||
|
self._gservice_request_uris.append(uri)
|
||
|
return (200, {}, datetime.now())
|
||
|
|
||
|
with patch.object(GoogleService, '_do_request', autospec=True, wraps=GoogleService, side_effect=_mock_do_request):
|
||
|
yield
|
||
|
|
||
|
def assertGoogleEventDeleted(self, google_id):
|
||
|
self.assertIn(google_id, self._gsync_deleted_ids, "Event should have been deleted")
|
||
|
|
||
|
def assertGoogleEventNotDeleted(self):
|
||
|
self.assertFalse(self._gsync_deleted_ids)
|
||
|
|
||
|
def assertGoogleEventInserted(self, values, timeout=None):
|
||
|
self.assertEqual(len(self._gsync_insert_values), 1)
|
||
|
matching = []
|
||
|
for insert_values, insert_kwargs in self._gsync_insert_values:
|
||
|
if all(insert_values.get(key, False) == value for key, value in values.items()):
|
||
|
matching.append((insert_values, insert_kwargs))
|
||
|
self.assertGreaterEqual(len(matching), 1, 'There must be at least 1 matching insert.')
|
||
|
insert_values, insert_kwargs = matching[0]
|
||
|
self.assertDictEqual(insert_kwargs, {'timeout': timeout} if timeout else {})
|
||
|
|
||
|
def assertGoogleEventNotInserted(self):
|
||
|
self.assertFalse(self._gsync_insert_values)
|
||
|
|
||
|
def assertGoogleEventPatched(self, google_id, values, timeout=None):
|
||
|
patch_values_all = self._gsync_patch_values.get(google_id)
|
||
|
self.assertTrue(patch_values_all)
|
||
|
matching = []
|
||
|
for patch_values, patch_kwargs in patch_values_all:
|
||
|
if all(patch_values.get(key, False) == values[key] for key in values):
|
||
|
matching.append((patch_values, patch_kwargs))
|
||
|
self.assertGreaterEqual(len(matching), 1, 'There must be at least 1 matching patch.')
|
||
|
patch_values, patch_kwargs = matching[0]
|
||
|
self.assertDictEqual(patch_kwargs, {'timeout': timeout} if timeout else {})
|
||
|
|
||
|
def assertGoogleEventNotPatched(self):
|
||
|
self.assertFalse(self._gsync_patch_values)
|
||
|
|
||
|
def assertGoogleAPINotCalled(self):
|
||
|
self.assertGoogleEventNotPatched()
|
||
|
self.assertGoogleEventNotInserted()
|
||
|
self.assertGoogleEventNotDeleted()
|
||
|
|
||
|
def assertGoogleEventSendUpdates(self, expected_value):
|
||
|
self.assertEqual(len(self._gservice_request_uris), 1)
|
||
|
uri = self._gservice_request_uris[0]
|
||
|
uri_parameter = "sendUpdates=%s" % expected_value
|
||
|
self.assertIn(uri_parameter, uri, "The URL should contain %s" % uri_parameter)
|
||
|
|
||
|
def call_post_commit_hooks(self):
|
||
|
"""
|
||
|
manually calls postcommit hooks defined with the decorator @after_commit
|
||
|
"""
|
||
|
|
||
|
funcs = self.env.cr.postcommit._funcs.copy()
|
||
|
while funcs:
|
||
|
func = funcs.popleft()
|
||
|
func()
|