[IMP] (website_)event(_sale/_question/_track): clean and improve tests

PURPOSE

As event will soon evolve (onchange -> compute, code improvements, addition of
new features) cleaning and improving tests is necessary to help avoid issues.

SPECIFICATIONS

Clean existing tests: lessen data / variables, try to remove unnecessary
tests or merge duplicates.

Add new tests, notably event type configuration copy onto event records
is not well tested. Event computed fields are also more tested.

Some access tests are added, more a base for future addition as only a few
use cases are covered.

LINKS

Side effect of Task ID 2089156 (event onchange to compute)
Community PR odoo/odoo#43127
Enterprise PR odoo/enterprise#7656
This commit is contained in:
Thibault Delavallée
2020-01-10 13:24:25 +00:00
parent eeac89f055
commit 5ee901dcb1
11 changed files with 384 additions and 94 deletions
+4 -1
View File
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_event_flow, test_mail_schedule
from . import test_event_flow
from . import test_event_internals
from . import test_event_mail_schedule
+59 -23
View File
@@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from odoo import fields
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.tests import common
@@ -12,36 +14,70 @@ class TestEventCommon(common.SavepointCase):
def setUpClass(cls):
super(TestEventCommon, cls).setUpClass()
# User groups
cls.group_employee_id = cls.env.ref('base.group_user').id
cls.group_event_user_id = cls.env.ref('event.group_event_user').id
cls.group_event_manager_id = cls.env.ref('event.group_event_manager').id
cls.group_system_id = cls.env.ref('base.group_system').id
# Test users to use through the various tests
cls.user_eventuser = cls.env['res.users'].with_context({'no_reset_password': True}).create({
'name': 'Armande EventUser',
'login': 'Armande',
'email': 'armande.eventuser@example.com',
'tz': 'Europe/Brussels',
'groups_id': [(6, 0, [cls.group_employee_id, cls.group_event_user_id])]
})
cls.user_eventmanager = cls.env['res.users'].with_context({'no_reset_password': True}).create({
'name': 'Bastien EventManager',
'login': 'bastien',
'email': 'bastien.eventmanager@example.com',
'tz': 'Europe/Brussels',
'groups_id': [(6, 0, [
cls.group_employee_id,
cls.group_event_manager_id,
cls.group_system_id])]
})
cls.user_portal = mail_new_test_user(
cls.env, login='portal_test',
name='Patrick Portal', email='patrick.portal@test.example.com',
notification_type='email', company_id=cls.env.ref("base.main_company").id,
groups='base.group_portal')
cls.user_employee = mail_new_test_user(
cls.env, login='user_employee',
name='Eglantine Employee', email='eglantine.employee@test.example.com',
tz='Europe/Brussels', notification_type='inbox',
company_id=cls.env.ref("base.main_company").id,
groups='base.group_user',
)
cls.user_eventuser = mail_new_test_user(
cls.env, login='user_eventuser',
name='Ursule EventUser', email='ursule.eventuser@test.example.com',
tz='Europe/Brussels', notification_type='inbox',
company_id=cls.env.ref("base.main_company").id,
groups='base.group_user,event.group_event_user',
)
cls.user_eventmanager = mail_new_test_user(
cls.env, login='user_eventmanager',
name='Martine EventManager', email='martine.eventmanager@test.example.com',
tz='Europe/Brussels', notification_type='inbox',
company_id=cls.env.ref("base.main_company").id,
groups='base.group_user,event.group_event_manager',
)
cls.customer = cls.env['res.partner'].create({
'name': 'Constantin Customer',
'email': 'constantin@example.com',
'country_id': cls.env.ref('base.be').id,
'phone': '0485112233',
})
cls.event_type_complex = cls.env['event.type'].create({
'name': 'Update Type',
'auto_confirm': True,
'is_online': False,
'has_seats_limitation': True,
'default_registration_min': 10,
'default_registration_max': 30,
'use_timezone': True,
'default_timezone': 'Europe/Paris',
'use_hashtag': True,
'default_hashtag': 'amazing',
'use_mail_schedule': True,
'event_type_mail_ids': [
(0, 0, { # right at subscription
'interval_unit': 'now',
'interval_type': 'after_sub',
'template_id': cls.env['ir.model.data'].xmlid_to_res_id('event.event_subscription')}),
(0, 0, { # 1 days before event
'interval_nbr': 1,
'interval_unit': 'days',
'interval_type': 'before_event',
'template_id': cls.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')}),
],
})
cls.event_0 = cls.env['event.event'].create({
'name': 'TestEvent',
'auto_confirm': True,
'date_begin': fields.Datetime.to_string(datetime.today() + timedelta(days=1)),
'date_end': fields.Datetime.to_string(datetime.today() + timedelta(days=15)),
'date_tz': 'Europe/Brussels',
})
# set country in order to format belgium numbers
+5 -64
View File
@@ -1,22 +1,19 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from dateutil.relativedelta import relativedelta
from odoo.addons.event.tests.common import TestEventCommon
from odoo.exceptions import ValidationError, UserError, AccessError
from odoo.exceptions import ValidationError
from odoo.tools import mute_logger
from odoo.fields import Datetime
try:
from unittest.mock import patch
except ImportError:
from mock import patch
class TestEventFlow(TestEventCommon):
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_00_basic_event_auto_confirm(self):
def test_event_auto_confirm(self):
""" Basic event management with auto confirmation """
# EventUser creates a new event: ok
test_event = self.env['event.event'].with_user(self.user_eventmanager).create({
@@ -58,7 +55,7 @@ class TestEventFlow(TestEventCommon):
self.assertEqual(test_event.seats_used, 2, 'Event: incorrect number of attendees after closing registration')
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_10_advanced_event_flow(self):
def test_event_flow(self):
""" Avanced event flow: no auto confirmation, manage minimum / maximum
seats, ... """
# EventUser creates a new event: ok
@@ -77,59 +74,3 @@ class TestEventFlow(TestEventCommon):
self.assertEqual(
test_reg1.state, 'draft',
'Event: new registration should not be confirmed with auto_confirmation parameter being False')
def test_event_access_rights(self):
# EventManager required to create or update events
with self.assertRaises(AccessError):
self.env['event.event'].with_user(self.user_eventuser).create({
'name': 'TestEvent',
'date_begin': datetime.datetime.now() + relativedelta(days=-1),
'date_end': datetime.datetime.now() + relativedelta(days=1),
'seats_max': 10,
})
with self.assertRaises(AccessError):
self.event_0.with_user(self.user_eventuser).write({
'name': 'TestEvent Modified',
})
# Settings access rights required to enable some features
self.user_eventmanager.write({'groups_id': [
(3, self.env.ref('base.group_system').id),
(4, self.env.ref('base.group_erp_manager').id)
]})
with self.assertRaises(AccessError):
event_config = self.env['res.config.settings'].with_user(self.user_eventmanager).create({
})
event_config.execute()
def test_event_data(self):
self.event_0.write({'registration_ids': [(0, 0, {'partner_id': self.user_eventuser.partner_id.id})]})
self.assertEqual(self.event_0.registration_ids.get_date_range_str(), u'tomorrow')
self.event_0.write({
'date_begin': '2019-11-09 14:30:00',
'date_end': '2019-11-10 00:00:00',
'date_tz': 'Mexico/General'
})
self.assertTrue(self.event_0.is_one_day)
def test_event_date_range(self):
self.event_0.write({'registration_ids': [(0, 0, {'partner_id': self.user_eventuser.partner_id.id})]})
self.patcher = patch('odoo.addons.event.models.event.fields.Datetime', wraps=Datetime)
self.mock_datetime = self.patcher.start()
self.mock_datetime.now.return_value = datetime.datetime(2015, 12, 31, 12, 0)
self.event_0.date_begin = datetime.datetime(2015, 12, 31, 18, 0)
self.assertEqual(self.event_0.registration_ids.get_date_range_str(), u'today')
self.event_0.date_begin = datetime.datetime(2016, 1, 1, 6, 0)
self.assertEqual(self.event_0.registration_ids.get_date_range_str(), u'tomorrow')
self.event_0.date_begin = datetime.datetime(2016, 1, 2, 6, 0)
self.assertEqual(self.event_0.registration_ids.get_date_range_str(), u'in 2 days')
self.mock_datetime.now.return_value = datetime.datetime(2015, 12, 10, 12, 0)
self.event_0.date_begin = datetime.datetime(2016, 1, 25, 6, 0)
self.assertEqual(self.event_0.registration_ids.get_date_range_str(), u'next month')
self.patcher.stop()
+243
View File
@@ -0,0 +1,243 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from unittest.mock import patch
from odoo.addons.event.tests.common import TestEventCommon
from odoo.exceptions import AccessError
from odoo.fields import Datetime as FieldsDatetime
from odoo.tests.common import users
from odoo.tools import mute_logger
class TestEventData(TestEventCommon):
@users('user_eventmanager')
def test_event_date_computation(self):
self.patcher = patch('odoo.addons.event.models.event.fields.Datetime', wraps=FieldsDatetime)
self.mock_datetime = self.patcher.start()
self.mock_datetime.now.return_value = datetime(2020, 1, 31, 8, 0, 0)
event = self.event_0.with_user(self.env.user)
event.write({
'registration_ids': [(0, 0, {'partner_id': self.customer.id})],
'date_begin': datetime(2020, 1, 31, 15, 0, 0),
'date_end': datetime(2020, 4, 5, 18, 0, 0),
})
registration = event.registration_ids[0]
self.assertEqual(registration.get_date_range_str(), u'today')
event.date_begin = datetime(2020, 2, 1, 15, 0, 0)
self.assertEqual(registration.get_date_range_str(), u'tomorrow')
event.date_begin = datetime(2020, 2, 2, 6, 0, 0)
self.assertEqual(registration.get_date_range_str(), u'in 2 days')
event.date_begin = datetime(2020, 2, 20, 17, 0, 0)
self.assertEqual(registration.get_date_range_str(), u'next month')
event.date_begin = datetime(2020, 3, 1, 10, 0, 0)
self.assertEqual(registration.get_date_range_str(), u'on Mar 1, 2020, 11:00:00 AM')
event.write({
'date_begin': '2019-11-09 14:30:00',
'date_end': '2019-11-10 02:00:00',
'date_tz': 'Mexico/General'
})
self.assertTrue(event.is_one_day)
self.patcher.stop()
@users('user_eventmanager')
def test_event_fields(self):
event_type = self.event_type_complex.with_user(self.env.user)
event = self.env['event.event'].create({
'name': 'Event Update Type',
'event_type_id': event_type.id,
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
})
event._onchange_type()
self.assertFalse(event.is_online)
self.assertEqual(event.address_id, self.env.user.company_id.partner_id)
# seats: coming from event type configuration
self.assertEqual(event.seats_availability, 'limited')
self.assertEqual(event.seats_available, event.event_type_id.default_registration_max)
self.assertEqual(event.seats_unconfirmed, 0)
self.assertEqual(event.seats_reserved, 0)
self.assertEqual(event.seats_used, 0)
self.assertEqual(event.seats_expected, 0)
# set is_online: should reset the address_id field
event.update({'is_online': True})
event._onchange_is_online()
self.assertTrue(event.is_online)
self.assertFalse(event.address_id)
# create registration in order to check the seats computation
self.assertTrue(event.auto_confirm)
for x in range(5):
reg = self.env['event.registration'].create({
'event_id': event.id
})
self.assertEqual(reg.state, 'open')
reg_draft = self.env['event.registration'].create({
'event_id': event.id
})
reg_draft.write({'state': 'draft'})
reg_done = self.env['event.registration'].create({
'event_id': event.id
})
reg_done.write({'state': 'done'})
self.assertEqual(event.seats_available, event.event_type_id.default_registration_max - 6)
self.assertEqual(event.seats_unconfirmed, 1)
self.assertEqual(event.seats_reserved, 5)
self.assertEqual(event.seats_used, 1)
self.assertEqual(event.seats_expected, 7)
@users('user_eventmanager')
@mute_logger('odoo.models.unlink')
def test_event_type_configuration(self):
self.assertEqual(self.env.user.tz, 'Europe/Brussels')
event_type = self.event_type_complex.with_user(self.env.user)
event_type.write({
'use_mail_schedule': False,
})
# self.assertEqual(event_type.event_type_mail_ids, self.env['event.type.mail']) # TDE FIXME: currently crashing
event = self.env['event.event'].create({
'name': 'Event Update Type',
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
'auto_confirm': False,
'twitter_hashtag': 'somuchwow',
'is_online': True,
})
self.assertEqual(event.date_tz, self.env.user.tz)
self.assertEqual(event.seats_availability, 'unlimited')
self.assertFalse(event.auto_confirm)
self.assertEqual(event.twitter_hashtag, 'somuchwow')
self.assertTrue(event.is_online)
self.assertEqual(event.event_mail_ids, self.env['event.mail'])
event.update({'event_type_id': event_type.id})
event._onchange_type()
self.assertEqual(event.date_tz, 'Europe/Paris')
self.assertEqual(event.seats_availability, 'limited')
self.assertEqual(event.seats_min, event_type.default_registration_min)
self.assertEqual(event.seats_max, event_type.default_registration_max)
self.assertTrue(event.auto_confirm)
self.assertEqual(event.twitter_hashtag, event_type.default_hashtag)
self.assertFalse(event.is_online)
# self.assertEqual(event.event_mail_ids, self.env['event.mail']) # TDE FIXME: currently crashing
event_type.write({
'use_mail_schedule': True,
'event_type_mail_ids': [(5, 0), (0, 0, {
'interval_nbr': 1, 'interval_unit': 'days', 'interval_type': 'before_event',
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')})]
})
event._onchange_type()
self.assertEqual(event.event_mail_ids.interval_nbr, 1)
self.assertEqual(event.event_mail_ids.interval_unit, 'days')
self.assertEqual(event.event_mail_ids.interval_type, 'before_event')
self.assertEqual(event.event_mail_ids.template_id, self.env.ref('event.event_reminder'))
class TestEventSecurity(TestEventCommon):
@users('user_employee')
@mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model')
def test_event_access_employee(self):
# employee can read events (sure ?)
event = self.event_0.with_user(self.env.user)
event.read(['name'])
# event.stage_id.read(['name', 'description'])
# event.event_type_id.read(['name', 'has_seats_limitation'])
with self.assertRaises(AccessError):
self.env['event.event'].create({
'name': 'TestEvent',
'date_begin': datetime.now() + relativedelta(days=-1),
'date_end': datetime.now() + relativedelta(days=1),
'seats_max': 10,
})
with self.assertRaises(AccessError):
event.write({
'name': 'TestEvent Modified',
})
with self.assertRaises(AccessError):
self.env['event.stage'].create({
'name': 'TestStage',
})
@users('user_eventuser')
@mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model')
def test_event_access_event_user(self):
event = self.event_0.with_user(self.env.user)
event.read(['name', 'user_id', 'kanban_state_label'])
with self.assertRaises(AccessError):
self.env['event.event'].create({
'name': 'TestEvent',
'date_begin': datetime.now() + relativedelta(days=-1),
'date_end': datetime.now() + relativedelta(days=1),
'seats_max': 10,
})
with self.assertRaises(AccessError):
event.write({
'name': 'TestEvent Modified',
})
# with self.assertRaises(AccessError):
# self.env['event.stage'].create({
# 'name': 'TestStage',
# })
@users('user_eventmanager')
@mute_logger('odoo.models.unlink', 'odoo.addons.base.models.ir_model')
def test_event_access_event_manager(self):
# EventManager can do about everything
event_type = self.env['event.type'].create({
'name': 'ManagerEventType',
'use_mail_schedule': True,
'event_type_mail_ids': [(5, 0), (0, 0, {
'interval_nbr': 1, 'interval_unit': 'days', 'interval_type': 'before_event',
'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')})]
})
event = self.env['event.event'].create({
'name': 'ManagerEvent',
'date_begin': datetime.now() + relativedelta(days=-1),
'date_end': datetime.now() + relativedelta(days=1),
})
event.update({'event_type_id': event_type.id})
event._onchange_type()
event.flush()
registration = self.env['event.registration'].create({'event_id': event.id})
registration.write({'name': 'Myself'})
stage = self.env.ref('event.event_stage_done')
stage.write({'name': 'ManagerEnded'})
event.write({'stage_id': stage.id})
registration.unlink()
event.unlink()
stage.unlink()
event_type.unlink()
# Settings access rights required to enable some features
self.user_eventmanager.write({'groups_id': [
(3, self.env.ref('base.group_system').id),
(4, self.env.ref('base.group_erp_manager').id)
]})
with self.assertRaises(AccessError):
event_config = self.env['res.config.settings'].with_user(self.user_eventmanager).create({
})
event_config.execute()
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from dateutil.relativedelta import relativedelta
from odoo import fields, tools
from odoo import fields
from odoo.addons.event.tests.common import TestEventCommon
from odoo.tools import mute_logger
@@ -11,7 +11,7 @@ from odoo.tools import mute_logger
class TestMailSchedule(TestEventCommon):
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_00_event_mail_schedule(self):
def test_event_mail_schedule(self):
""" Test mail scheduling for events """
now = fields.Datetime.now()
event_date_begin = now + relativedelta(days=1)
+1 -2
View File
@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from odoo.tests import common
from odoo.fields import Datetime
from unittest.mock import patch
class EventSaleTest(common.TransactionCase):
+1 -1
View File
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta
from odoo.addons.event.tests.common import TestEventCommon
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.sms.tests.common import MockSMS
from odoo.tools import mute_logger
class TestSMSSchedule(TestEventCommon, MockSMS):
@@ -4,3 +4,4 @@
from . import controllers
from . import models
from . import report
from . import tests
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import common
from . import test_event_internals
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.event.tests.common import TestEventCommon
class TestEventQuestionCommon(TestEventCommon):
@classmethod
def setUpClass(cls):
super(TestEventQuestionCommon, cls).setUpClass()
cls.event_question_1 = cls.env['event.question'].create({
'title': 'Question1',
'event_type_id': cls.event_type_complex.id,
'is_individual': True,
'answer_ids': [
(0, 0, {'name': 'Q1-Answer1'}),
(0, 0, {'name': 'Q1-Answer2'})
],
})
cls.event_question_2 = cls.env['event.question'].create({
'title': 'Question2',
'event_type_id': cls.event_type_complex.id,
'is_individual': False,
'answer_ids': [
(0, 0, {'name': 'Q2-Answer1'}),
(0, 0, {'name': 'Q2-Answer2'})
],
})
cls.event_type_complex.write({'use_questions': True})
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from odoo.addons.website_event_questions.tests.common import TestEventQuestionCommon
from odoo.fields import Datetime as FieldsDatetime
from odoo.tests.common import users
class TestEventData(TestEventQuestionCommon):
@users('user_eventmanager')
def test_event_type_configuration(self):
event_type = self.event_type_complex.with_user(self.env.user)
event = self.env['event.event'].create({
'name': 'Event Update Type',
'event_type_id': event_type.id,
'date_begin': FieldsDatetime.to_string(datetime.today() + timedelta(days=1)),
'date_end': FieldsDatetime.to_string(datetime.today() + timedelta(days=15)),
})
event._onchange_type()
self.assertEqual(event.specific_question_ids.title, 'Question1')
self.assertEqual(
set(event.specific_question_ids.mapped('answer_ids.name')),
set(['Q1-Answer1', 'Q1-Answer2']))
self.assertEqual(event.general_question_ids.title, 'Question2')
self.assertEqual(
set(event.general_question_ids.mapped('answer_ids.name')),
set(['Q2-Answer1', 'Q2-Answer2']))