19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:28 +01:00
parent 20ddc1b4a3
commit c0efcc53f5
1162 changed files with 125577 additions and 105287 deletions

View file

@ -1,33 +1,41 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import MagicMock, patch
from collections import defaultdict
from contextlib import contextmanager
from datetime import datetime
from freezegun import freeze_time
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 GoogleSync
from odoo.tests.common import HttpCase, new_test_user
from freezegun import freeze_time
from contextlib import contextmanager
from odoo.addons.google_calendar.models.res_users import ResUsers
from odoo.addons.google_calendar.models.google_sync import google_calendar_token, GoogleCalendarSync
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.tests.common import HttpCase
from odoo.tools import mute_logger
def patch_api(func):
@patch.object(GoogleSync, '_google_insert', MagicMock(spec=GoogleSync._google_insert))
@patch.object(GoogleSync, '_google_delete', MagicMock(spec=GoogleSync._google_delete))
@patch.object(GoogleSync, '_google_patch', MagicMock(spec=GoogleSync._google_patch))
def patched(self, *args, **kwargs):
return func(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.organizer_user = new_test_user(self.env, login="organizer_user")
self.attendee_user = new_test_user(self.env, login='attendee_user')
@patch.object(ResUsers, '_get_google_calendar_token', lambda user: 'dummy-token')
class TestSyncGoogle(HttpCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.google_service = GoogleCalendarService(cls.env['google.service'])
cls.env.user.sudo().unpause_google_synchronization()
cls.organizer_user = mail_new_test_user(cls.env, login="organizer_user")
cls.attendee_user = mail_new_test_user(cls.env, login='attendee_user')
m = mute_logger('odoo.addons.auth_signup.models.res_users')
mute_logger.__enter__(m) # noqa: PLC2801
cls.addClassCleanup(mute_logger.__exit__, m, None, None, None)
@contextmanager
def mock_datetime_and_now(self, mock_dt):
@ -40,36 +48,89 @@ class TestSyncGoogle(HttpCase):
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(GoogleCalendarSync, '_google_insert', autospec=True, wraps=GoogleCalendarSync, side_effect=_mock_insert), \
patch.object(GoogleCalendarSync, '_google_delete', autospec=True, wraps=GoogleCalendarSync, side_effect=_mock_delete), \
patch.object(GoogleCalendarSync, '_google_patch', autospec=True, wraps=GoogleCalendarSync, 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):
GoogleSync._google_delete.assert_called()
args, dummy = GoogleSync._google_delete.call_args
self.assertEqual(args[1], google_id, "Event should have been deleted")
self.assertIn(google_id, self._gsync_deleted_ids, "Event should have been deleted")
def assertGoogleEventNotDeleted(self):
GoogleSync._google_delete.assert_not_called()
self.assertFalse(self._gsync_deleted_ids)
def assertGoogleEventInserted(self, values, timeout=None):
expected_args = (values,)
expected_kwargs = {'timeout': timeout} if timeout else {}
GoogleSync._google_insert.assert_called_once()
args, kwargs = GoogleSync._google_insert.call_args
args[1:][0].pop('conferenceData', None)
self.assertEqual(args[1:], expected_args) # skip Google service arg
self.assertEqual(kwargs, expected_kwargs)
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 assertGoogleEventInsertedMultiTime(self, values, timeout=None):
self.assertGreaterEqual(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):
GoogleSync._google_insert.assert_not_called()
self.assertFalse(self._gsync_insert_values)
def assertGoogleEventPatched(self, google_id, values, timeout=None):
expected_args = (google_id, values)
expected_kwargs = {'timeout': timeout} if timeout else {}
GoogleSync._google_patch.assert_called_once()
args, kwargs = GoogleSync._google_patch.call_args
self.assertEqual(args[1:], expected_args) # skip Google service arg
self.assertEqual(kwargs, expected_kwargs)
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):
GoogleSync._google_patch.assert_not_called()
self.assertFalse(self._gsync_patch_values)
def assertGoogleAPINotCalled(self):
self.assertGoogleEventNotPatched()
@ -77,10 +138,10 @@ class TestSyncGoogle(HttpCase):
self.assertGoogleEventNotDeleted()
def assertGoogleEventSendUpdates(self, expected_value):
GoogleService._do_request.assert_called_once()
args, _ = GoogleService._do_request.call_args
val = "sendUpdates=%s" % expected_value
self.assertTrue(val in args[0], "The URL should contain %s" % val)
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):
"""
@ -91,8 +152,3 @@ class TestSyncGoogle(HttpCase):
while funcs:
func = funcs.popleft()
func()
def assertGoogleEventHasNoConferenceData(self):
GoogleSync._google_insert.assert_called_once()
args, _ = GoogleSync._google_insert.call_args
self.assertFalse(args[1].get('conferenceData', False))