[REF][MOV] test(_mass)_mail(_sms): move sms tests in their own addon

In this commit we introduce a new module ``test_mail_sms`` that holds the
tests for sms application, like ``test_mail`` does for mail. Currently all
sms tests are inside ``test_mail_full``. After this commit code is moved
from ``test_mail_full`` into that module. Full testing module should be used
mainly to test integrations with a lot of submodules and for performance
tests, not testing details of SMS implementation.

We also add ``mass_mailing_sms`` as dependency of ``test_mass_mailing`` so
that both mailing types are tested in the same module. It eases maintenance
and writing of tests. Mass mailing SMS tests  from `test_mail_full`` are
therefore moved in ``test_mass_mailing``.

This commit also allows some cleaning in classes used in tests, to have
classes in ``test_mail_sms`` and ``test_mail_full`` that contain everything
necessary to test mail features.

Task-2890111 (Test Mail/Mass Mailing: SMS tests reorganization and move)

Part-of: odoo/odoo#96223
This commit is contained in:
Thibault Delavallée
2022-07-19 11:51:12 +02:00
parent 106193e359
commit 039c63cf6e
34 changed files with 318 additions and 248 deletions
+3 -2
View File
@@ -1,12 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import Form, users
from odoo.exceptions import AccessError
from odoo.addons.mail.tests.common import MailCommon
from odoo.exceptions import AccessError
from odoo.tests import Form, users
class TestMailTemplate(MailCommon):
@classmethod
def setUpClass(cls):
super(TestMailTemplate, cls).setUpClass()
+3 -2
View File
@@ -6,11 +6,12 @@ import re
import werkzeug
from odoo import tools
from odoo.addons.link_tracker.tests.common import MockLinkTracker
from odoo.addons.mass_mailing.tests.common import MassMailCommon
from odoo.addons.sms.tests.common import SMSCase, SMSCommon
class MassSMSCase(SMSCase):
class MassSMSCase(SMSCase, MockLinkTracker):
# ------------------------------------------------------------
# ASSERTS
@@ -155,7 +156,7 @@ class MassSMSCase(SMSCase):
)
class MassSMSCommon(MassMailCommon, SMSCommon, MassSMSCase):
class MassSMSCommon(SMSCommon, MassSMSCase, MassMailCommon):
@classmethod
def setUpClass(cls):
+1 -1
View File
@@ -249,7 +249,7 @@ class SMSCase(MockSMS):
self.assertEqual(tools.html2plaintext(message.body).rstrip('\n'), body)
class SMSCommon(MailCommon, MockSMS):
class SMSCommon(MailCommon, SMSCase):
@classmethod
def setUpClass(cls):
+3 -2
View File
@@ -11,8 +11,6 @@ and mail-related sub modules. Those tests are present in a separate module as it
contains models used only to perform tests independently to functional aspects of
real applications. """,
'depends': [
'test_mail',
'test_mass_mailing',
'mail',
'mail_bot',
'portal',
@@ -22,6 +20,9 @@ real applications. """,
'mass_mailing_sms', # adds portal
'phone_validation',
'sms',
'test_mail',
'test_mail_sms',
'test_mass_mailing',
],
'data': [
'data/mail_message_subtype_data.xml',
-1
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from . import test_mail_models_mail
from . import test_mail_models_sms
@@ -4,15 +4,3 @@ access_mail_test_portal_user,mail.test.portal.user,model_mail_test_portal,base.g
access_mail_test_rating_all,mail.test.rating.all,model_mail_test_rating,,0,0,0,0
access_mail_test_rating_portal,mail.test.rating.portal,model_mail_test_rating,base.group_portal,1,0,0,0
access_mail_test_rating_user,mail.test.rating.user,model_mail_test_rating,base.group_user,1,1,1,1
access_mail_test_sms_all,mail.test.sms.all,model_mail_test_sms,,0,0,0,0
access_mail_test_sms_user,mail.test.sms.user,model_mail_test_sms,base.group_user,1,1,1,1
access_mail_test_sms_bl_all,mail.test.sms.bl.all,model_mail_test_sms_bl,,0,0,0,0
access_mail_test_sms_bl_user,mail.test.sms.bl.user,model_mail_test_sms_bl,base.group_user,1,1,1,1
access_mail_test_sms_bl_activity_all,mail.test.sms.bl.activity.all,model_mail_test_sms_bl_activity,,0,0,0,0
access_mail_test_sms_bl_activity_user,mail.test.sms.bl.activity.user,model_mail_test_sms_bl_activity,base.group_user,1,1,1,1
access_mail_test_sms_bl_optout_all,mail.test.sms.bl.optout.all,model_mail_test_sms_bl_optout,,0,0,0,0
access_mail_test_sms_bl_optout_user,mail.test.sms.bl.optout.user,model_mail_test_sms_bl_optout,base.group_user,1,1,1,1
access_mail_test_sms_partner_all,mail.test.sms.partner.all,model_mail_test_sms_partner,,0,0,0,0
access_mail_test_sms_partner_user,mail.test.sms.partner.user,model_mail_test_sms_partner,base.group_user,1,1,1,1
access_mail_test_sms_partner_2many_all,mail.test.sms.partner.2many.all,model_mail_test_sms_partner_2many,,0,0,0,0
access_mail_test_sms_partner_2many_user,mail.test.sms.partner.2many.user,model_mail_test_sms_partner_2many,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
4 access_mail_test_rating_all mail.test.rating.all model_mail_test_rating 0 0 0 0
5 access_mail_test_rating_portal mail.test.rating.portal model_mail_test_rating base.group_portal 1 0 0 0
6 access_mail_test_rating_user mail.test.rating.user model_mail_test_rating base.group_user 1 1 1 1
access_mail_test_sms_all mail.test.sms.all model_mail_test_sms 0 0 0 0
access_mail_test_sms_user mail.test.sms.user model_mail_test_sms base.group_user 1 1 1 1
access_mail_test_sms_bl_all mail.test.sms.bl.all model_mail_test_sms_bl 0 0 0 0
access_mail_test_sms_bl_user mail.test.sms.bl.user model_mail_test_sms_bl base.group_user 1 1 1 1
access_mail_test_sms_bl_activity_all mail.test.sms.bl.activity.all model_mail_test_sms_bl_activity 0 0 0 0
access_mail_test_sms_bl_activity_user mail.test.sms.bl.activity.user model_mail_test_sms_bl_activity base.group_user 1 1 1 1
access_mail_test_sms_bl_optout_all mail.test.sms.bl.optout.all model_mail_test_sms_bl_optout 0 0 0 0
access_mail_test_sms_bl_optout_user mail.test.sms.bl.optout.user model_mail_test_sms_bl_optout base.group_user 1 1 1 1
access_mail_test_sms_partner_all mail.test.sms.partner.all model_mail_test_sms_partner 0 0 0 0
access_mail_test_sms_partner_user mail.test.sms.partner.user model_mail_test_sms_partner base.group_user 1 1 1 1
access_mail_test_sms_partner_2many_all mail.test.sms.partner.2many.all model_mail_test_sms_partner_2many 0 0 0 0
access_mail_test_sms_partner_2many_user mail.test.sms.partner.2many.user model_mail_test_sms_partner_2many base.group_user 1 1 1 1
+1 -11
View File
@@ -1,19 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import common
from . import test_odoobot
from . import test_mail_performance
from . import test_phone_blacklist
from . import test_mass_mailing
from . import test_mass_mailing_statistics
from . import test_mass_sms
from . import test_portal
from . import test_rating
from . import test_res_users
from . import test_sms_composer
from . import test_sms_management
from . import test_sms_performance
from . import test_sms_post
from . import test_sms_server_actions
from . import test_sms_sms
from . import test_sms_template
+2 -50
View File
@@ -1,56 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.mass_mailing_sms.tests.common import MassSMSCommon
from odoo.addons.test_mail.tests import common
from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon
class TestMailFullCommon(TestMassMailCommon, MassSMSCommon):
@classmethod
def setUpClass(cls):
super(TestMailFullCommon, cls).setUpClass()
cls.mailing_sms = cls.env['mailing.mailing'].with_user(cls.user_marketing).create({
'name': 'XMas SMS',
'subject': 'Xmas SMS for {object.name}',
'mailing_model_id': cls.env['ir.model']._get('mail.test.sms').id,
'mailing_type': 'sms',
'mailing_domain': '%s' % repr([('name', 'ilike', 'MassSMSTest')]),
'body_plaintext': 'Dear {{object.display_name}} this is a mass SMS with two links http://www.odoo.com/smstest and http://www.odoo.com/smstest/{{object.id}}',
'sms_force_send': True,
'sms_allow_unsubscribe': True,
})
@classmethod
def _create_mailing_sms_test_records(cls, model='mail.test.sms', partners=None, count=1):
""" Helper to create data. Currently simple, to be improved. """
Model = cls.env[model]
phone_field = 'phone_nbr' if 'phone_nbr' in Model else 'phone'
partner_field = 'customer_id' if 'customer_id' in Model else 'partner_id'
vals_list = []
for idx in range(count):
vals = {
'name': 'MassSMSTestRecord_%02d' % idx,
phone_field: '045600%02d%02d' % (idx, idx)
}
if partners:
vals[partner_field] = partners[idx % len(partners)]
vals_list.append(vals)
return cls.env[model].create(vals_list)
class TestMailFullRecipients(common.TestRecipients):
@classmethod
def setUpClass(cls):
super(TestMailFullRecipients, cls).setUpClass()
cls.partner_numbers = [
phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164')
for partner in (cls.partner_1 | cls.partner_2)
]
class TestMailFullCommon(TestMassMailCommon):
""" Keep a single entry point, notably for backward compatibility """
+3 -2
View File
@@ -4,13 +4,14 @@
import json
from odoo import http
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon
from odoo.addons.test_mail_sms.tests.common import TestSMSRecipients
from odoo.tests import tagged, users
from odoo.tests.common import HttpCase
@tagged('portal')
class TestPortal(HttpCase, TestMailFullCommon, TestMailFullRecipients):
class TestPortal(HttpCase, TestMailFullCommon, TestSMSRecipients):
def setUp(self):
super(TestPortal, self).setUp()
+3 -2
View File
@@ -3,13 +3,14 @@
from datetime import datetime
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon
from odoo.addons.test_mail_sms.tests.common import TestSMSRecipients
from odoo.tests import tagged
from odoo.tests.common import HttpCase, users, warmup
from odoo.tools import mute_logger
class TestRatingCommon(TestMailFullCommon, TestMailFullRecipients):
class TestRatingCommon(TestMailFullCommon, TestSMSRecipients):
@classmethod
def setUpClass(cls):
super(TestRatingCommon, cls).setUpClass()
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon
class TestResUsers(MailCommon):
class TestResUsers(TestMailFullCommon):
@classmethod
def setUpClass(cls):
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
{
'name': 'SMS Tests',
'version': '1.0',
'category': 'Hidden',
'sequence': 9876,
'summary': 'SMS Tests: performances and tests specific to SMS',
'description': """This module contains tests related to SMS. Those are
present in a separate module as it contains models used only to perform
tests independently to functional aspects of other models. """,
'depends': [
'mail',
'sms',
'test_performance',
],
'data': [
'security/ir.model.access.csv',
],
'installable': True,
'license': 'LGPL-3',
}
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_mail_sms_models
@@ -0,0 +1,13 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mail_test_sms_all,mail.test.sms.all,model_mail_test_sms,,0,0,0,0
access_mail_test_sms_user,mail.test.sms.user,model_mail_test_sms,base.group_user,1,1,1,1
access_mail_test_sms_bl_all,mail.test.sms.bl.all,model_mail_test_sms_bl,,0,0,0,0
access_mail_test_sms_bl_user,mail.test.sms.bl.user,model_mail_test_sms_bl,base.group_user,1,1,1,1
access_mail_test_sms_bl_activity_all,mail.test.sms.bl.activity.all,model_mail_test_sms_bl_activity,,0,0,0,0
access_mail_test_sms_bl_activity_user,mail.test.sms.bl.activity.user,model_mail_test_sms_bl_activity,base.group_user,1,1,1,1
access_mail_test_sms_bl_optout_all,mail.test.sms.bl.optout.all,model_mail_test_sms_bl_optout,,0,0,0,0
access_mail_test_sms_bl_optout_user,mail.test.sms.bl.optout.user,model_mail_test_sms_bl_optout,base.group_user,1,1,1,1
access_mail_test_sms_partner_all,mail.test.sms.partner.all,model_mail_test_sms_partner,,0,0,0,0
access_mail_test_sms_partner_user,mail.test.sms.partner.user,model_mail_test_sms_partner,base.group_user,1,1,1,1
access_mail_test_sms_partner_2many_all,mail.test.sms.partner.2many.all,model_mail_test_sms_partner_2many,,0,0,0,0
access_mail_test_sms_partner_2many_user,mail.test.sms.partner.2many.user,model_mail_test_sms_partner_2many,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mail_test_sms_all mail.test.sms.all model_mail_test_sms 0 0 0 0
3 access_mail_test_sms_user mail.test.sms.user model_mail_test_sms base.group_user 1 1 1 1
4 access_mail_test_sms_bl_all mail.test.sms.bl.all model_mail_test_sms_bl 0 0 0 0
5 access_mail_test_sms_bl_user mail.test.sms.bl.user model_mail_test_sms_bl base.group_user 1 1 1 1
6 access_mail_test_sms_bl_activity_all mail.test.sms.bl.activity.all model_mail_test_sms_bl_activity 0 0 0 0
7 access_mail_test_sms_bl_activity_user mail.test.sms.bl.activity.user model_mail_test_sms_bl_activity base.group_user 1 1 1 1
8 access_mail_test_sms_bl_optout_all mail.test.sms.bl.optout.all model_mail_test_sms_bl_optout 0 0 0 0
9 access_mail_test_sms_bl_optout_user mail.test.sms.bl.optout.user model_mail_test_sms_bl_optout base.group_user 1 1 1 1
10 access_mail_test_sms_partner_all mail.test.sms.partner.all model_mail_test_sms_partner 0 0 0 0
11 access_mail_test_sms_partner_user mail.test.sms.partner.user model_mail_test_sms_partner base.group_user 1 1 1 1
12 access_mail_test_sms_partner_2many_all mail.test.sms.partner.2many.all model_mail_test_sms_partner_2many 0 0 0 0
13 access_mail_test_sms_partner_2many_user mail.test.sms.partner.2many.user model_mail_test_sms_partner_2many base.group_user 1 1 1 1
+11
View File
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_phone_blacklist
from . import test_sms_composer
from . import test_sms_management
from . import test_sms_performance
from . import test_sms_post
from . import test_sms_server_actions
from . import test_sms_sms
from . import test_sms_template
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.sms.tests.common import SMSCommon
from odoo.addons.test_mail.tests.common import TestMailCommon, TestRecipients
class TestSMSCommon(SMSCommon, TestMailCommon):
""" Main entry point for functional tests. Kept to ease backward
compatibility and updating common. """
class TestSMSRecipients(TestRecipients):
@classmethod
def setUpClass(cls):
super(TestSMSRecipients, cls).setUpClass()
cls.partner_numbers = [
phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164')
for partner in (cls.partner_1 | cls.partner_2)
]
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
class TestPhoneBlacklist(TestMailFullCommon, TestMailFullRecipients):
""" TODO """
class TestPhoneBlacklist(TestSMSCommon, TestSMSRecipients):
""" Test phone blacklist management """
@classmethod
def setUpClass(cls):
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
class TestSMSComposerComment(TestMailFullCommon, TestMailFullRecipients):
class TestSMSComposerComment(TestSMSCommon, TestSMSRecipients):
""" TODO LIST
* add test for default_res_model / default_res_id and stuff like that;
@@ -206,7 +206,7 @@ class TestSMSComposerComment(TestMailFullCommon, TestMailFullRecipients):
self.assertSMSIapSent(self.random_numbers_san, self._test_body)
class TestSMSComposerBatch(TestMailFullCommon):
class TestSMSComposerBatch(TestSMSCommon):
@classmethod
def setUpClass(cls):
super(TestSMSComposerBatch, cls).setUpClass()
@@ -248,7 +248,7 @@ class TestSMSComposerBatch(TestMailFullCommon):
self.assertSMSNotification([{'partner': r.customer_id} for r in self.records], 'Zizisse an SMS.', messages)
class TestSMSComposerMass(TestMailFullCommon):
class TestSMSComposerMass(TestSMSCommon):
@classmethod
def setUpClass(cls):
@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
from odoo.tests import tagged
from odoo.tools import mute_logger
class TestSMSActionsCommon(TestMailFullCommon, TestMailFullRecipients):
class TestSMSActionsCommon(TestSMSCommon, TestSMSRecipients):
@classmethod
def setUpClass(cls):
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
class TestSMSPost(TestMailFullCommon, TestMailFullRecipients):
class TestSMSPost(TestSMSCommon, TestSMSRecipients):
""" TODO
* add tests for new mail.message and mail.thread fields;
@@ -251,7 +251,7 @@ class TestSMSPost(TestMailFullCommon, TestMailFullRecipients):
self.assertSMSNotification([{'partner': self.partner_1, 'number': self.test_numbers_san[1]}], 'Dear %s this is an SMS.' % self.test_record.display_name, messages)
class TestSMSPostException(TestMailFullCommon, TestMailFullRecipients):
class TestSMSPostException(TestSMSCommon, TestSMSRecipients):
@classmethod
def setUpClass(cls):
@@ -392,7 +392,7 @@ class TestSMSPostException(TestMailFullCommon, TestMailFullRecipients):
], self._test_body, messages)
class TestSMSApi(TestMailFullCommon):
class TestSMSApi(TestSMSCommon):
@classmethod
def setUpClass(cls):
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
class TestServerAction(TestMailFullCommon, TestMailFullRecipients):
class TestServerAction(TestSMSCommon, TestSMSRecipients):
@classmethod
def setUpClass(cls):
+105
View File
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import patch
from unittest.mock import DEFAULT
from odoo import exceptions
from odoo.addons.link_tracker.tests.common import MockLinkTracker
from odoo.addons.sms.models.sms_sms import SmsSms as SmsModel
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon
from odoo.tests import tagged
@tagged('link_tracker')
class TestSMSPost(TestSMSCommon, MockLinkTracker):
@classmethod
def setUpClass(cls):
super(TestSMSPost, cls).setUpClass()
cls._test_body = 'VOID CONTENT'
cls.sms_all = cls.env['sms.sms']
for x in range(10):
cls.sms_all |= cls.env['sms.sms'].create({
'number': '+324560000%s%s' % (x, x),
'body': cls._test_body,
})
def test_sms_send_batch_size(self):
self.count = 0
def _send(sms_self, unlink_failed=False, unlink_sent=True, raise_exception=False):
self.count += 1
return DEFAULT
self.env['ir.config_parameter'].set_param('sms.session.batch.size', '3')
with patch.object(SmsModel, '_send', autospec=True, side_effect=_send) as _send_mock:
self.env['sms.sms'].browse(self.sms_all.ids).send()
self.assertEqual(self.count, 4)
def test_sms_send_crash_employee(self):
with self.assertRaises(exceptions.AccessError):
self.env['sms.sms'].with_user(self.user_employee).browse(self.sms_all.ids).send()
def test_sms_send_delete_all(self):
with self.mockSMSGateway(sms_allow_unlink=True, sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=True, unlink_sent=True, raise_exception=False)
self.assertFalse(len(self.sms_all.exists()))
def test_sms_send_delete_default(self):
""" Test default send behavior: keep failed SMS, remove sent. """
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'credit',
'+32456000033': 'server_error',
'+32456000044': 'unregistered',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 4)
self.assertTrue(all(sms.state == 'error') for sms in remaining)
def test_sms_send_delete_failed(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=True, unlink_sent=False, raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 8)
self.assertTrue(all(sms.state == 'sent') for sms in remaining)
def test_sms_send_delete_none(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=False, unlink_sent=False, raise_exception=False)
self.assertEqual(len(self.sms_all.exists()), 10)
success_sms = self.sms_all[:1] + self.sms_all[3:]
error_sms = self.sms_all[1:3]
self.assertTrue(all(sms.state == 'sent') for sms in success_sms)
self.assertTrue(all(sms.state == 'error') for sms in error_sms)
def test_sms_send_delete_sent(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=False, unlink_sent=True, raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 2)
self.assertTrue(all(sms.state == 'error') for sms in remaining)
def test_sms_send_raise(self):
with self.assertRaises(exceptions.AccessError):
with self.mockSMSGateway(sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=True)
self.assertEqual(set(self.sms_all.mapped('state')), set(['outgoing']))
def test_sms_send_raise_catch(self):
with self.mockSMSGateway(sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=False)
self.assertEqual(set(self.sms_all.mapped('state')), set(['error']))
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon, TestMailFullRecipients
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon, TestSMSRecipients
class TestSmsTemplate(TestMailFullCommon, TestMailFullRecipients):
class TestSmsTemplate(TestSMSCommon, TestSMSRecipients):
@classmethod
def setUpClass(cls):
+6 -1
View File
@@ -9,7 +9,12 @@
'description': """This module contains tests related to mass mailing. Those
are present in a separate module to use specific test models defined in
test_mail. """,
'depends': ['test_mail', 'mass_mailing'],
'depends': [
'mass_mailing',
'mass_mailing_sms',
'test_mail',
'test_mail_sms',
],
'data': [
'security/ir.model.access.csv',
],
@@ -5,8 +5,11 @@ from . import test_blacklist
from . import test_blacklist_behavior
from . import test_blacklist_mixin
from . import test_link_tracker
from . import test_link_tracker_sms
from . import test_mailing
from . import test_mailing_server
from . import test_mailing_sms
from . import test_mailing_statistics
from . import test_mailing_statistics_sms
from . import test_mailing_test
from . import test_performance
+76 -3
View File
@@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mass_mailing.tests.common import MassMailCommon
from odoo.addons.test_mail.tests.common import TestMailCommon
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.mass_mailing_sms.tests.common import MassSMSCommon
from odoo.addons.test_mail_sms.tests.common import TestSMSCommon
class TestMassMailCommon(MassMailCommon, TestMailCommon):
class TestMassMailCommon(MassSMSCommon, TestSMSCommon):
@classmethod
def setUpClass(cls):
@@ -43,11 +45,42 @@ class TestMassMailCommon(MassMailCommon, TestMailCommon):
'reply_to_mode': 'update',
})
cls.mailing_sms = cls.env['mailing.mailing'].with_user(cls.user_marketing).create({
'name': 'XMas SMS',
'subject': 'Xmas SMS for {object.name}',
'mailing_model_id': cls.env['ir.model']._get('mail.test.sms').id,
'mailing_type': 'sms',
'mailing_domain': '%s' % repr([('name', 'ilike', 'MassSMSTest')]),
'body_plaintext': 'Dear {{object.display_name}} this is a mass SMS with two links http://www.odoo.com/smstest and http://www.odoo.com/smstest/{{object.id}}',
'sms_force_send': True,
'sms_allow_unsubscribe': True,
})
@classmethod
def _create_test_blacklist_records(cls, model='mailing.test.blacklist', count=1):
""" Deprecated, remove in 14.4 """
return cls.__create_mailing_test_records(model=model, count=count)
@classmethod
def _create_mailing_sms_test_records(cls, model='mail.test.sms', partners=None, count=1):
""" Helper to create data. Currently simple, to be improved. """
Model = cls.env[model]
phone_field = 'phone_nbr' if 'phone_nbr' in Model else 'phone'
partner_field = 'customer_id' if 'customer_id' in Model else 'partner_id'
vals_list = []
for idx in range(count):
vals = {
'name': 'MassSMSTestRecord_%02d' % idx,
phone_field: '045600%02d%02d' % (idx, idx)
}
if partners:
vals[partner_field] = partners[idx % len(partners)]
vals_list.append(vals)
return cls.env[model].create(vals_list)
@classmethod
def _create_mailing_test_records(cls, model='mailing.test.blacklist', partners=None, count=1):
""" Helper to create data. Currently simple, to be improved. """
@@ -67,3 +100,43 @@ class TestMassMailCommon(MassMailCommon, TestMailCommon):
vals_list.append(vals)
return cls.env[model].create(vals_list)
class TestMassSMSCommon(TestMassMailCommon):
@classmethod
def setUpClass(cls):
super(TestMassSMSCommon, cls).setUpClass()
cls._test_body = 'Mass SMS in your face'
records = cls.env['mail.test.sms']
partners = cls.env['res.partner']
country_be_id = cls.env.ref('base.be').id
_country_us_id = cls.env.ref('base.us').id
for x in range(10):
partners += cls.env['res.partner'].with_context(**cls._test_context).create({
'name': 'Partner_%s' % (x),
'email': '_test_partner_%s@example.com' % (x),
'country_id': country_be_id,
'mobile': '045600%s%s99' % (x, x)
})
records += cls.env['mail.test.sms'].with_context(**cls._test_context).create({
'name': 'MassSMSTest_%s' % (x),
'customer_id': partners[x].id,
'phone_nbr': '045600%s%s44' % (x, x)
})
cls.records = cls._reset_mail_context(records)
cls.records_numbers = [phone_validation.phone_format(r.phone_nbr, 'BE', '32', force_format='E164') for r in cls.records]
cls.partners = partners
cls.sms_template = cls.env['sms.template'].create({
'name': 'Test Template',
'model_id': cls.env['ir.model']._get('mail.test.sms').id,
'body': 'Dear {{ object.display_name }} this is a mass SMS.',
})
cls.partner_numbers = [
phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164')
for partner in partners
]
@@ -1,20 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import werkzeug
from unittest.mock import patch
from unittest.mock import DEFAULT
from odoo import exceptions
from odoo.addons.link_tracker.tests.common import MockLinkTracker
from odoo.addons.sms.models.sms_sms import SmsSms as SmsSms
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon
from odoo.addons.test_mass_mailing.tests.common import TestMassMailCommon
from odoo.tests import tagged
@tagged('link_tracker')
class TestSMSPost(TestMailFullCommon, MockLinkTracker):
class TestSMSPost(TestMassMailCommon):
@classmethod
def setUpClass(cls):
@@ -121,81 +113,3 @@ class TestSMSPost(TestMailFullCommon, MockLinkTracker):
self.assertEqual(
res[sms_4.id],
f'Welcome to {self._web_base_url}/r/RAOUL/s/{sms_4.id}\nAnd again,\n{self._web_base_url}/r/RAOUL/s/{sms_4.id}')
def test_sms_send_batch_size(self):
self.count = 0
def _send(sms_self, unlink_failed=False, unlink_sent=True, raise_exception=False):
self.count += 1
return DEFAULT
self.env['ir.config_parameter'].set_param('sms.session.batch.size', '3')
with patch.object(SmsSms, '_send', autospec=True, side_effect=_send) as send_mock:
self.env['sms.sms'].browse(self.sms_all.ids).send()
self.assertEqual(self.count, 4)
def test_sms_send_crash_employee(self):
with self.assertRaises(exceptions.AccessError):
self.env['sms.sms'].with_user(self.user_employee).browse(self.sms_all.ids).send()
def test_sms_send_delete_all(self):
with self.mockSMSGateway(sms_allow_unlink=True, sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=True, unlink_sent=True, raise_exception=False)
self.assertFalse(len(self.sms_all.exists()))
def test_sms_send_delete_default(self):
""" Test default send behavior: keep failed SMS, remove sent. """
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'credit',
'+32456000033': 'server_error',
'+32456000044': 'unregistered',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 4)
self.assertTrue(all(sms.state == 'error') for sms in remaining)
def test_sms_send_delete_failed(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=True, unlink_sent=False, raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 8)
self.assertTrue(all(sms.state == 'sent') for sms in remaining)
def test_sms_send_delete_none(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=False, unlink_sent=False, raise_exception=False)
self.assertEqual(len(self.sms_all.exists()), 10)
success_sms = self.sms_all[:1] + self.sms_all[3:]
error_sms = self.sms_all[1:3]
self.assertTrue(all(sms.state == 'sent') for sms in success_sms)
self.assertTrue(all(sms.state == 'error') for sms in error_sms)
def test_sms_send_delete_sent(self):
with self.mockSMSGateway(sms_allow_unlink=True, nbr_t_error={
'+32456000011': 'wrong_number_format',
'+32456000022': 'wrong_number_format',
}):
self.env['sms.sms'].browse(self.sms_all.ids).send(unlink_failed=False, unlink_sent=True, raise_exception=False)
remaining = self.sms_all.exists()
self.assertEqual(len(remaining), 2)
self.assertTrue(all(sms.state == 'error') for sms in remaining)
def test_sms_send_raise(self):
with self.assertRaises(exceptions.AccessError):
with self.mockSMSGateway(sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=True)
self.assertEqual(set(self.sms_all.mapped('state')), set(['outgoing']))
def test_sms_send_raise_catch(self):
with self.mockSMSGateway(sim_error='jsonrpc_exception'):
self.env['sms.sms'].browse(self.sms_all.ids).send(raise_exception=False)
self.assertEqual(set(self.sms_all.mapped('state')), set(['error']))
@@ -4,55 +4,14 @@
from ast import literal_eval
from odoo.addons.phone_validation.tools import phone_validation
from odoo.addons.test_mail_full.tests.common import TestMailFullCommon
from odoo.addons.test_mass_mailing.tests.common import TestMassSMSCommon
from odoo import exceptions
from odoo.tests import tagged
from odoo.tests.common import users
from odoo.tools import mute_logger
@tagged('mass_mailing')
class TestMassSMSCommon(TestMailFullCommon):
@classmethod
def setUpClass(cls):
super(TestMassSMSCommon, cls).setUpClass()
cls._test_body = 'Mass SMS in your face'
records = cls.env['mail.test.sms']
partners = cls.env['res.partner']
country_be_id = cls.env.ref('base.be').id,
country_us_id = cls.env.ref('base.us').id,
for x in range(10):
partners += cls.env['res.partner'].with_context(**cls._test_context).create({
'name': 'Partner_%s' % (x),
'email': '_test_partner_%s@example.com' % (x),
'country_id': country_be_id,
'mobile': '045600%s%s99' % (x, x)
})
records += cls.env['mail.test.sms'].with_context(**cls._test_context).create({
'name': 'MassSMSTest_%s' % (x),
'customer_id': partners[x].id,
'phone_nbr': '045600%s%s44' % (x, x)
})
cls.records = cls._reset_mail_context(records)
cls.records_numbers = [phone_validation.phone_format(r.phone_nbr, 'BE', '32', force_format='E164') for r in cls.records]
cls.partners = partners
cls.sms_template = cls.env['sms.template'].create({
'name': 'Test Template',
'model_id': cls.env['ir.model']._get('mail.test.sms').id,
'body': 'Dear {{ object.display_name }} this is a mass SMS.',
})
cls.partner_numbers = [
phone_validation.phone_format(partner.mobile, partner.country_id.code, partner.country_id.phone_code, force_format='E164')
for partner in partners
]
@tagged('mass_mailing')
@tagged('mass_mailing', 'mass_mailing_sms')
class TestMassSMSInternals(TestMassSMSCommon):
@users('user_marketing')
@@ -11,7 +11,7 @@ from odoo.tests import tagged
from odoo.tools import mute_logger
@tagged('digest')
@tagged('digest', 'mass_mailing')
class TestMailingStatistics(TestMassMailCommon):
@classmethod
@@ -4,13 +4,13 @@
from lxml import html
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.test_mail_full.tests.test_mass_sms import TestMassSMSCommon
from odoo.addons.test_mass_mailing.tests.common import TestMassSMSCommon
from odoo.tests.common import users
from odoo.tests import tagged
from odoo.tools import mute_logger
@tagged('digest', 'mass_mailing')
@tagged('digest', 'mass_mailing', 'mass_mailing_sms')
class TestMailingStatistics(TestMassSMSCommon):
@classmethod
@@ -46,14 +46,14 @@ class TestMassMailPerformance(TestMassMailPerformanceBase):
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
})
# runbot needs +1 compared to local
with self.assertQueryCount(__system__=425, marketing=426):
# runbot needs +2 compared to local
with self.assertQueryCount(__system__=426, marketing=427):
mailing.action_send_mail()
self.assertEqual(mailing.sent, 50)
self.assertEqual(mailing.delivered, 50)
# runbot needs +2 compared to local
# runbot needs +3 compared to local
with self.assertQueryCount(__system__=69, marketing=67):
self.env['mail.mail'].sudo().search([('to_delete', '=', True)]).unlink()
@@ -93,14 +93,14 @@ class TestMassMailBlPerformance(TestMassMailPerformanceBase):
'mailing_domain': [('id', 'in', self.mm_recs.ids)],
})
# runbot needs +1 compared to local
with self.assertQueryCount(__system__=487, marketing=488):
# runbot needs +2 compared to local
with self.assertQueryCount(__system__=488, marketing=489):
mailing.action_send_mail()
self.assertEqual(mailing.sent, 50)
self.assertEqual(mailing.delivered, 50)
# runbot needs +2 compared to local
# runbot needs +3 compared to local
with self.assertQueryCount(__system__=69, marketing=67):
self.env['mail.mail'].sudo().search([('to_delete', '=', True)]).unlink()