diff options
| author | Thibault Delavallée <tde@odoo.com> | 2021-03-19 13:31:59 +0000 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2021-03-19 16:36:20 +0000 |
| commit | 1a66d9cb57dc17b697b7a56effa91de3a4b50bd7 (patch) | |
| tree | e62caf0cbbca0e8058396112ec4c8577c3a5704c /addons/event | |
| parent | 3ad9126375e74071fec47f402f1fc63f98b755b6 (diff) | |
[IMP] event: improve tests about communication scheduling
In this commit we improve event communication scheduling tests. We make tests
more detailed and use mail tools to ensure content. We also check scheduled
dates and use freezegun to ease date management.
Related to Task ID-2414658
COM PR odoo/odoo#68158
Diffstat (limited to 'addons/event')
| -rw-r--r-- | addons/event/tests/test_event_mail_schedule.py | 286 |
1 files changed, 233 insertions, 53 deletions
diff --git a/addons/event/tests/test_event_mail_schedule.py b/addons/event/tests/test_event_mail_schedule.py index 42e1d18017d..c7c61ee56c1 100644 --- a/addons/event/tests/test_event_mail_schedule.py +++ b/addons/event/tests/test_event_mail_schedule.py @@ -1,76 +1,256 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from datetime import datetime from dateutil.relativedelta import relativedelta +from freezegun import freeze_time -from odoo import fields from odoo.addons.event.tests.common import TestEventCommon -from odoo.tools import mute_logger +from odoo.addons.mail.tests.common import MockEmail +from odoo.tools import formataddr, mute_logger -class TestMailSchedule(TestEventCommon): +class TestMailSchedule(TestEventCommon, MockEmail): @mute_logger('odoo.addons.base.models.ir_model', 'odoo.models') def test_event_mail_schedule(self): """ Test mail scheduling for events """ - now = fields.Datetime.now() - event_date_begin = now + relativedelta(days=1) - event_date_end = now + relativedelta(days=3) - - test_event = self.env['event.event'].with_user(self.user_eventmanager).create({ - 'name': 'TestEventMail', - 'auto_confirm': True, - 'date_begin': event_date_begin, - 'date_end': event_date_end, - 'event_mail_ids': [ - (0, 0, { # right at subscription - 'interval_unit': 'now', - 'interval_type': 'after_sub', - 'template_id': self.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': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')}), - ] - }) + event_cron_id = self.env.ref('event.event_mail_scheduler') - # create some registrations - self.env['event.registration'].with_user(self.user_eventuser).create({ - 'event_id': test_event.id, - 'name': 'Reg0', - 'email': 'reg0@example.com', - }) - self.env['event.registration'].with_user(self.user_eventuser).create({ - 'event_id': test_event.id, - 'name': 'Reg1', - 'email': 'reg1@example.com', - }) + # deactivate other schedulers to avoid messing with crons + self.env['event.mail'].search([]).unlink() + + # freeze some datetimes, and ensure more than 1D+1H before event starts + # to ease time-based scheduler check + now = datetime(2021, 3, 20, 14, 30, 15) + event_date_begin = datetime(2021, 3, 22, 8, 0, 0) + event_date_end = datetime(2021, 3, 24, 18, 0, 0) + + with freeze_time(now): + test_event = self.env['event.event'].with_user(self.user_eventmanager).create({ + 'name': 'TestEventMail', + 'auto_confirm': True, + 'date_begin': event_date_begin, + 'date_end': event_date_end, + 'event_mail_ids': [ + (0, 0, { # right at subscription + 'interval_unit': 'now', + 'interval_type': 'after_sub', + 'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_subscription')}), + (0, 0, { # one day after subscription + 'interval_nbr': 1, + 'interval_unit': 'hours', + 'interval_type': 'after_sub', + 'template_id': self.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': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')}), + (0, 0, { # immediately after event + 'interval_nbr': 1, + 'interval_unit': 'hours', + 'interval_type': 'after_event', + 'template_id': self.env['ir.model.data'].xmlid_to_res_id('event.event_reminder')}), + ] + }) # check subscription scheduler - schedulers = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub')]) - self.assertEqual(len(schedulers), 1, 'event: wrong scheduler creation') - self.assertEqual(schedulers[0].scheduled_date, test_event.create_date, 'event: incorrect scheduled date for checking controller') + after_sub_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub'), ('interval_unit', '=', 'now')]) + self.assertEqual(len(after_sub_scheduler), 1, 'event: wrong scheduler creation') + self.assertEqual(after_sub_scheduler.scheduled_date, test_event.create_date) + self.assertTrue(after_sub_scheduler.done) + after_sub_scheduler_2 = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_sub'), ('interval_unit', '=', 'hours')]) + self.assertEqual(len(after_sub_scheduler_2), 1, 'event: wrong scheduler creation') + self.assertEqual(after_sub_scheduler_2.scheduled_date, test_event.create_date + relativedelta(hours=1)) + self.assertTrue(after_sub_scheduler_2.done) + # check before event scheduler + event_prev_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'before_event')]) + self.assertEqual(len(event_prev_scheduler), 1, 'event: wrong scheduler creation') + self.assertEqual(event_prev_scheduler.scheduled_date, event_date_begin + relativedelta(days=-1)) + self.assertFalse(event_prev_scheduler.done) + # check after event scheduler + event_next_scheduler = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'after_event')]) + self.assertEqual(len(event_next_scheduler), 1, 'event: wrong scheduler creation') + self.assertEqual(event_next_scheduler.scheduled_date, event_date_end + relativedelta(hours=1)) + self.assertFalse(event_next_scheduler.done) + + # create some registrations + with freeze_time(now), self.mock_mail_gateway(): + reg1 = self.env['event.registration'].with_user(self.user_eventuser).create({ + 'event_id': test_event.id, + 'name': 'Reg1', + 'email': 'reg1@example.com', + }) + reg2 = self.env['event.registration'].with_user(self.user_eventuser).create({ + 'event_id': test_event.id, + 'name': 'Reg2', + 'email': 'reg2@example.com', + }) + + # REGISTRATIONS / PRE SCHEDULERS + # -------------------------------------------------- + + # check registration state + self.assertTrue(all(reg.state == 'open' for reg in reg1 + reg2), 'Registrations: should be auto-confirmed') + self.assertTrue(all(reg.date_open == now for reg in reg1 + reg2), 'Registrations: should have open date set to confirm date') # verify that subscription scheduler was auto-executed after each registration - self.assertEqual(len(schedulers[0].mail_registration_ids), 2, 'event: incorrect number of mail scheduled date') + self.assertEqual(len(after_sub_scheduler.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)') + for mail_registration in after_sub_scheduler.mail_registration_ids: + self.assertEqual(mail_registration.scheduled_date, now) + self.assertTrue(mail_registration.mail_sent, 'event: registration mail should be sent at registration creation') + self.assertTrue(after_sub_scheduler.done, 'event: all subscription mails should have been sent') - mails = self.env['mail.mail'].sudo().search([('subject', 'ilike', 'registration'), ('date', '>=', now)], order='date DESC', limit=3) - self.assertEqual(len(mails), 2, 'event: wrong number of registration mail sent') + # check emails effectively sent + self.assertEqual(len(self._new_mails), 2, 'event: should have 2 scheduled emails (1 / registration)') + self.assertMailMailWEmails( + [formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))], + 'outgoing', '', + fields_values={'subject': 'Your registration at %s' % test_event.name, + 'email_from': self.user_eventmanager.company_id.email_formatted, + }) - for registration in schedulers[0].mail_registration_ids: - self.assertTrue(registration.mail_sent, 'event: wrongly confirmed mailing on registration') + # same for second scheduler: scheduled but not sent + self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)') + for mail_registration in after_sub_scheduler_2.mail_registration_ids: + self.assertEqual(mail_registration.scheduled_date, now + relativedelta(hours=1)) + self.assertFalse(mail_registration.mail_sent, 'event: registration mail should be scheduled, not sent') + self.assertFalse(after_sub_scheduler_2.done, 'event: all subscription mails should be scheduled, not sent') - # check before event scheduler - schedulers = self.env['event.mail'].search([('event_id', '=', test_event.id), ('interval_type', '=', 'before_event')]) - self.assertEqual(len(schedulers), 1, 'event: wrong scheduler creation') - self.assertEqual(schedulers[0].scheduled_date, event_date_begin + relativedelta(days=-1), 'event: incorrect scheduled date') + # execute event reminder scheduler explicitly, before scheduled date -> should not do anything + with freeze_time(now), self.mock_mail_gateway(): + after_sub_scheduler_2.execute() + self.assertFalse(any(mail_reg.mail_sent for mail_reg in after_sub_scheduler_2.mail_registration_ids)) + self.assertFalse(after_sub_scheduler_2.done) + self.assertEqual(len(self._new_mails), 0, 'event: should not send mails before scheduled date') + + # execute event reminder scheduler explicitly, right at scheduled date -> should sent mails + now_registration = now + relativedelta(hours=1) + with freeze_time(now_registration), self.mock_mail_gateway(): + after_sub_scheduler_2.execute() + + # verify that subscription scheduler was auto-executed after each registration + self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 2, 'event: should have 2 scheduled communication (1 / registration)') + self.assertTrue(all(mail_reg.mail_sent for mail_reg in after_sub_scheduler_2.mail_registration_ids)) + # FIXME: field not updated + # self.assertTrue(after_sub_scheduler_2.done, 'event: all subscription mails should have been sent') + + # check emails effectively sent + self.assertEqual(len(self._new_mails), 2, 'event: should have 2 scheduled emails (1 / registration)') + self.assertMailMailWEmails( + [formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))], + 'outgoing', '', + fields_values={'subject': 'Your registration at %s' % test_event.name, + 'email_from': self.user_eventmanager.company_id.email_formatted, + }) + + # PRE SCHEDULERS (MOVE FORWARD IN TIME) + # -------------------------------------------------- + + self.assertFalse(event_prev_scheduler.mail_sent) + self.assertFalse(event_prev_scheduler.done) + + # execute event reminder scheduler explicitly, before scheduled date -> should not do anything + # FIXME: execute does not respect scheduled date + # now_start = event_date_begin + relativedelta(hours=-25) + # with freeze_time(now_start), self.mock_mail_gateway(): + # event_prev_scheduler.execute() + + # self.assertFalse(event_prev_scheduler.mail_sent) + # self.assertFalse(event_prev_scheduler.done) + # self.assertEqual(len(self._new_mails, 0)) + + # execute cron to run schedulers + now_start = event_date_begin + relativedelta(hours=-23) + with freeze_time(now_start), self.mock_mail_gateway(): + event_cron_id.method_direct_trigger() + + # check that scheduler is finished + self.assertTrue(event_prev_scheduler.mail_sent, 'event: reminder scheduler should have run') + self.assertTrue(event_prev_scheduler.done, 'event: reminder scheduler should have run') + + # check emails effectively sent + self.assertEqual(len(self._new_mails), 2, 'event: should have scheduled 2 mails (1 / registration)') + self.assertMailMailWEmails( + [formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email))], + 'outgoing', '', + fields_values={'subject': '%s: tomorrow' % test_event.name, + 'email_from': self.user_eventmanager.company_id.email_formatted, + }) + + # NEW REGISTRATION EFFECT ON SCHEDULERS + # -------------------------------------------------- + + test_event.write({'auto_confirm': False}) + with freeze_time(now_start), self.mock_mail_gateway(): + reg3 = self.env['event.registration'].with_user(self.user_eventuser).create({ + 'event_id': test_event.id, + 'name': 'Reg3', + 'email': 'reg3@example.com', + }) + + # no more seats + self.assertEqual(reg3.state, 'draft') + + # schedulers state untouched + self.assertTrue(event_prev_scheduler.mail_sent) + self.assertTrue(event_prev_scheduler.mail_sent) + self.assertFalse(event_next_scheduler.mail_sent) + self.assertFalse(event_next_scheduler.done) + self.assertFalse(after_sub_scheduler.done, 'event: scheduler registrations should be lower than effective registrations') + self.assertFalse(after_sub_scheduler_2.done, 'event: scheduler registrations should be lower than effective registrations') + + # confirm registration -> should trigger registration schedulers + # NOTE: currently all schedulers are based on date_open which equals create_date + # meaning several communications may be sent in the time time + with freeze_time(now_start + relativedelta(hours=1)), self.mock_mail_gateway(): + # FIXME: sudo should not be necessary + reg3.sudo().action_confirm() + + # verify that subscription scheduler was auto-executed after new registration confirmed + self.assertEqual(len(after_sub_scheduler.mail_registration_ids), 3, 'event: should have 3 scheduled communication (1 / registration)') + new_mail_reg = after_sub_scheduler.mail_registration_ids.filtered(lambda mail_reg: mail_reg.registration_id == reg3) + self.assertEqual(new_mail_reg.scheduled_date, now_start) + self.assertTrue(new_mail_reg.mail_sent, 'event: registration mail should be sent at registration creation') + self.assertTrue(after_sub_scheduler.done, 'event: all subscription mails should have been sent') + + # verify that subscription scheduler was auto-executed after new registration confirmed + self.assertEqual(len(after_sub_scheduler_2.mail_registration_ids), 3, 'event: should have 3 scheduled communication (1 / registration)') + new_mail_reg = after_sub_scheduler_2.mail_registration_ids.filtered(lambda mail_reg: mail_reg.registration_id == reg3) + self.assertEqual(new_mail_reg.scheduled_date, now_start + relativedelta(hours=1)) + self.assertTrue(new_mail_reg.mail_sent, 'event: registration mail should be sent at registration creation') + self.assertTrue(after_sub_scheduler_2.done, 'event: all subscription mails should have been sent') + + # check emails effectively sent + self.assertEqual(len(self._new_mails), 2, 'event: should have 1 scheduled emails (new registration only)') + # manual check because 2 identical mails are sent and mail tools do not support it easily + for mail in self._new_mails: + self.assertEqual(mail.email_from, self.user_eventmanager.company_id.email_formatted) + self.assertEqual(mail.subject, 'Your registration at %s' % test_event.name) + self.assertEqual(mail.state, 'outgoing') + self.assertEqual(mail.email_to, formataddr((reg3.name, reg3.email))) + + # POST SCHEDULERS (MOVE FORWARD IN TIME) + # -------------------------------------------------- + + self.assertFalse(event_next_scheduler.mail_sent) + self.assertFalse(event_next_scheduler.done) - # execute event reminder scheduler explicitly - schedulers[0].execute() + # execute event reminder scheduler explicitly after its schedule date + new_end = event_date_end + relativedelta(hours=2) + with freeze_time(new_end), self.mock_mail_gateway(): + event_cron_id.method_direct_trigger() - self.assertTrue(schedulers[0].mail_sent, 'event: reminder scheduler should have sent an email') - self.assertTrue(schedulers[0].done, 'event: reminder scheduler should be done') + # check that scheduler is finished + self.assertTrue(event_next_scheduler.mail_sent, 'event: reminder scheduler should should have run') + self.assertTrue(event_next_scheduler.done, 'event: reminder scheduler should have run') - mails = self.env['mail.mail'].sudo().search([('subject', 'ilike', 'TestEventMail'), ('date', '>=', now)], order='date DESC', limit=3) - self.assertEqual(len(mails), 3, 'event: wrong number of reminders in outgoing mail queue') + # check emails effectively sent + self.assertEqual(len(self._new_mails), 3, 'event: should have scheduled 3 mails, one for each registration') + self.assertMailMailWEmails( + [formataddr((reg1.name, reg1.email)), formataddr((reg2.name, reg2.email)), formataddr((reg3.name, reg3.email))], + 'outgoing', '', + fields_values={'subject': '%s: today' % test_event.name, + 'email_from': self.user_eventmanager.company_id.email_formatted, + }) |
