1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
|
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from freezegun import freeze_time
from unittest.mock import patch
from odoo import exceptions
from odoo.addons.mass_mailing.tests.common import MassMailCommon
from odoo.tests import Form, tagged, users
@tagged('mailing_list')
class TestMailingContactToList(MassMailCommon):
@users('user_marketing')
def test_mailing_contact_to_list(self):
contacts = self.env['mailing.contact'].create([{
'name': 'Contact %02d',
'email': 'contact_%02d@test.example.com',
} for x in range(30)])
self.assertEqual(len(contacts), 30)
self.assertEqual(contacts.list_ids, self.env['mailing.list'])
mailing = self.env['mailing.list'].create({
'name': 'Contacts Agregator',
})
# create wizard with context values
wizard_form = Form(self.env['mailing.contact.to.list'].with_context(default_contact_ids=contacts.ids))
self.assertEqual(wizard_form.contact_ids.ids, contacts.ids)
# set mailing list and add contacts
wizard_form.mailing_list_id = mailing
wizard = wizard_form.save()
action = wizard.action_add_contacts()
self.assertEqual(contacts.list_ids, mailing)
self.assertEqual(action["type"], "ir.actions.client")
self.assertTrue(action.get("params", {}).get("next"), "Should return a notification with a next action")
subaction = action["params"]["next"]
self.assertEqual(subaction["type"], "ir.actions.act_window_close")
# set mailing list, add contacts and redirect to mailing view
mailing2 = self.env['mailing.list'].create({
'name': 'Contacts Sublimator',
})
wizard_form.mailing_list_id = mailing2
wizard = wizard_form.save()
action = wizard.action_add_contacts_and_send_mailing()
self.assertEqual(contacts.list_ids, mailing + mailing2)
self.assertEqual(action["type"], "ir.actions.client")
self.assertTrue(action.get("params", {}).get("next"), "Should return a notification with a next action")
subaction = action["params"]["next"]
self.assertEqual(subaction["type"], "ir.actions.act_window")
self.assertEqual(subaction["context"]["default_contact_list_ids"], [mailing2.id])
@tagged('mailing_list')
class TestMailingListMerge(MassMailCommon):
@classmethod
def setUpClass(cls):
super(TestMailingListMerge, cls).setUpClass()
cls._create_mailing_list()
cls.mailing_list_3 = cls.env['mailing.list'].with_context(cls._test_context).create({
'name': 'ListC',
'contact_ids': [
(0, 0, {'name': 'Norberto', 'email': 'norbert@example.com'}),
]
})
@users('user_marketing')
def test_mailing_contact_create(self):
default_list_ids = (self.mailing_list_2 | self.mailing_list_3).ids
# simply set default list in context
new = self.env['mailing.contact'].with_context(default_list_ids=default_list_ids).create([{
'name': 'Contact_%d' % x,
'email': 'contact_%d@test.example.com' % x,
} for x in range(0, 5)])
self.assertEqual(new.list_ids, (self.mailing_list_2 | self.mailing_list_3))
# default list and subscriptions should be merged
new = self.env['mailing.contact'].with_context(default_list_ids=default_list_ids).create([{
'name': 'Contact_%d' % x,
'email': 'contact_%d@test.example.com' % x,
'subscription_ids': [(0, 0, {
'list_id': self.mailing_list_1.id,
'opt_out': True,
}), (0, 0, {
'list_id': self.mailing_list_2.id,
'opt_out': True,
})],
} for x in range(0, 5)])
self.assertEqual(new.list_ids, (self.mailing_list_1 | self.mailing_list_2 | self.mailing_list_3))
# should correctly take subscription opt_out value
for list_id in (self.mailing_list_1 | self.mailing_list_2).ids:
new = new.with_context(default_list_ids=[list_id])
self.assertTrue(all(contact.opt_out for contact in new))
# not opt_out for new subscription without specific create values
for list_id in self.mailing_list_3.ids:
new = new.with_context(default_list_ids=[list_id])
self.assertFalse(any(contact.opt_out for contact in new))
with freeze_time('2022-01-01 12:00'), \
patch.object(self.env.cr, 'now', lambda: datetime(2022, 1, 1, 12, 0, 0)):
contact_form = Form(self.env['mailing.contact'])
contact_form.name = 'Contact_test'
with contact_form.subscription_ids.new() as subscription:
subscription.list_id = self.mailing_list_1
subscription.opt_out = True
with contact_form.subscription_ids.new() as subscription:
subscription.list_id = self.mailing_list_2
subscription.opt_out = False
contact = contact_form.save()
self.assertEqual(contact.subscription_ids.filtered(lambda s: s.list_id == self.mailing_list_1).opt_out_datetime, datetime(2022, 1, 1, 12, 0, 0))
self.assertFalse(contact.subscription_ids.filtered(lambda s: s.list_id == self.mailing_list_2).opt_out_datetime)
@users('user_marketing')
def test_mailing_list_action_send_mailing(self):
mailing_ctx = self.mailing_list_1.action_send_mailing().get('context', {})
form = Form(self.env['mailing.mailing'].with_context(mailing_ctx))
form.subject = 'Test Mail'
mailing = form.save()
# Check that mailing model and mailing list are set properly
self.assertEqual(
mailing.mailing_model_id, self.env['ir.model']._get('mailing.list'),
'Should have correct mailing model set')
self.assertEqual(mailing.contact_list_ids, self.mailing_list_1, 'Should have correct mailing list set')
self.assertEqual(mailing.mailing_type, 'mail', 'Should have correct mailing_type')
@users('user_marketing')
def test_mailing_list_contact_copy_in_context_of_mailing_list(self):
MailingContact = self.env['mailing.contact']
contact_1 = MailingContact.create({
'name': 'Sam',
'email': 'gamgee@shire.com',
'subscription_ids': [(0, 0, {'list_id': self.mailing_list_3.id})],
})
# Copy the contact with default_list_ids in context, which should not raise anything
contact_2 = contact_1.with_context(default_list_ids=self.mailing_list_3.ids).copy()
self.assertEqual(contact_1.list_ids, contact_2.list_ids, 'Should copy the existing mailing list(s)')
@users('user_marketing')
def test_mailing_list_merge(self):
# TEST CASE: Merge A,B into the existing mailing list C
# The mailing list C contains the same email address than 'Norbert' in list B
# This test ensure that the mailing lists are correctly merged and no
# duplicates are appearing in C
merge_form = Form(self.env['mailing.list.merge'].with_context(
active_ids=[self.mailing_list_1.id, self.mailing_list_2.id],
active_model='mailing.list'
))
merge_form.new_list_name = False
merge_form.merge_options = 'existing'
# Need to set `merge_options` before `dest_lid_id` so `dest_list_id` is visible
# `'invisible': [('merge_options', '=', 'new')]`
merge_form.dest_list_id = self.mailing_list_3
merge_form.archive_src_lists = False
result_list = merge_form.save().action_mailing_lists_merge()
# Assert the number of contacts is correct
self.assertEqual(
len(result_list.contact_ids.ids), 5,
'The number of contacts on the mailing list C is not equal to 5')
# Assert there's no duplicated email address
self.assertEqual(
len(list(set(result_list.contact_ids.mapped('email')))), 5,
'Duplicates have been merged into the destination mailing list. Check %s' % (result_list.contact_ids.mapped('email')))
@users('user_marketing')
def test_mailing_list_merge_cornercase(self):
""" Check wrong use of merge wizard """
with self.assertRaises(exceptions.UserError):
merge_form = Form(self.env['mailing.list.merge'].with_context(
active_ids=[self.mailing_list_1.id, self.mailing_list_2.id],
))
merge_form = Form(self.env['mailing.list.merge'].with_context(
active_ids=[self.mailing_list_1.id],
active_model='mailing.list',
default_src_list_ids=[self.mailing_list_1.id, self.mailing_list_2.id],
default_dest_list_id=self.mailing_list_3.id,
default_merge_options='existing',
))
merge = merge_form.save()
self.assertEqual(merge.src_list_ids, self.mailing_list_1 + self.mailing_list_2)
self.assertEqual(merge.dest_list_id, self.mailing_list_3)
@tagged('mailing_list')
class TestMailingContactImport(MassMailCommon):
"""Test the transient <mailing.contact.import>."""
@users('user_marketing')
def test_mailing_contact_import(self):
first_list, second_list, third_list = self.env['mailing.list'].create([
{'name': 'First mailing list'},
{'name': 'Second mailing list'},
{'name': 'Third mailing list'},
])
self.env['mailing.contact'].create([
{
'name': 'Already Exists',
'email': 'already_exists_list_1@example.com',
'list_ids': first_list.ids,
}, {
'email': 'already_exists_list_2@example.com',
'list_ids': second_list.ids,
}, {
'email': 'already_exists_list_1_and_2@example.com',
'list_ids': (first_list | second_list).ids,
},
])
self.env['mailing.mailing'].create({
'name': 'Test',
'subject': 'Test',
'contact_list_ids': (first_list | second_list).ids,
})
contact_import = Form(self.env['mailing.contact.import'].with_context(
default_mailing_list_ids=first_list.ids,
))
contact_import.contact_list = '''
invalid line1
alice@example.com
bob@example.com
invalid line2
"Bob" <bob@EXAMPLE.com>
"Test" <bob@example.com>
invalid line3, with a comma
already_exists_list_1@example.com
already_exists_list_2@example.com
"Test" <already_exists_list_1_and_2@example.com>
invalid line4
'''
contact_import = contact_import.save()
self.assertEqual(contact_import.mailing_list_ids, first_list)
# Can not add many2many directly on a Form
contact_import.mailing_list_ids |= third_list
self.assertEqual(len(first_list.contact_ids), 2, 'Should not yet create the contact')
self.assertEqual(len(second_list.contact_ids), 2, 'Should not yet create the contact')
self.assertEqual(len(third_list.contact_ids), 0, 'Should not yet create the contact')
# Test that the context key "default_list_ids" is ignored (because we manually set list_ids)
contact_import.with_context(default_list_ids=(first_list | second_list).ids).action_import()
self.env['mailing.list'].invalidate_model(['contact_ids'])
# Check the contact of the first mailing list
contacts = [
(contact.name, contact.email)
for contact in first_list.contact_ids
]
self.assertIn(('', 'alice@example.com'), contacts, 'Should have imported the right email address')
self.assertIn(('Bob', 'bob@example.com'), contacts, 'Should have imported the name of the contact')
self.assertIn(
('', 'already_exists_list_2@example.com'), contacts,
'The email already exists but in a different list. The contact must be imported.')
self.assertEqual(len(second_list.contact_ids), 2, 'Should have ignored default_list_ids')
self.assertNotIn(('Test', 'bob@example.com'), contacts, 'Should have ignored duplicated')
self.assertNotIn(('', 'bob@example.com'), contacts, 'Should have ignored duplicated')
self.assertNotIn(('Test', 'already_exists_list_1_and_2@example.com'), contacts, 'Should have ignored duplicated')
self.assertEqual(len(contacts), 5, 'Should have imported 2 new contacts')
# Check the contact of the third mailing list
contacts = [
(contact.name, contact.email)
for contact in third_list.contact_ids
]
self.assertIn(('', 'alice@example.com'), contacts, 'Should have imported the right email address')
self.assertIn(('Bob', 'bob@example.com'), contacts, 'Should have imported the name of the contact')
self.assertIn(
('', 'already_exists_list_2@example.com'), contacts,
'The email already exists but in a different list. The contact must be imported.')
self.assertIn(('Already Exists', 'already_exists_list_1@example.com'), contacts, 'This contact exists in the first mailing list, but not in the third mailing list')
self.assertNotIn(('Test', 'already_exists_list_1_and_2@example.com'), contacts, 'Should have ignored duplicated')
contact = self.env['mailing.contact'].search([('email', '=', 'already_exists_list_1@example.com')])
self.assertEqual(len(contact), 1, 'Should have updated the existing contact instead of creating a new one')
@tagged('mailing_list')
class TestSubscriptionManagement(MassMailCommon):
@users('user_marketing')
def test_mailing_update_optout(self):
_email_formatted = '"Mireille Labeille" <mireille@test.example.com>'
_email_formatted_upd = '"Mireille Oreille-Labeille" <mireille@test.example.com>'
_email_normalized = 'mireille@test.example.com'
self._create_mailing_list()
ml_1, ml_2 = self.mailing_list_1.with_env(self.env), self.mailing_list_2.with_env(self.env)
ml_3 = self._create_mailing_list_of_x_contacts(3)
self.assertEqual(ml_1.contact_count, 3)
self.assertEqual(ml_1.contact_count_blacklisted, 0)
self.assertEqual(ml_1.contact_count_email, 3)
self.assertEqual(ml_1.contact_count_opt_out, 0)
self.assertEqual(ml_2.contact_count, 4)
self.assertEqual(ml_2.contact_count_blacklisted, 0)
self.assertEqual(ml_2.contact_count_email, 4)
self.assertEqual(ml_2.contact_count_opt_out, 0)
self.assertEqual(ml_3.contact_count, 3)
self.assertEqual(ml_3.contact_count_blacklisted, 0)
self.assertEqual(ml_3.contact_count_email, 3)
self.assertEqual(ml_3.contact_count_opt_out, 0)
# create a new test contact
contact = self.env['mailing.contact'].browse(
self.env['mailing.contact'].name_create(_email_formatted)[0]
)
self.assertEqual(contact.email, _email_normalized)
self.assertEqual(contact.name, 'Mireille Labeille')
# add new subscriptions (and ensure email_normalized is used)
(ml_1 + ml_2)._update_subscription_from_email(_email_formatted_upd, opt_out=False)
subs = self.env['mailing.subscription'].search(
[('contact_id', '=', contact.id)]
)
self.assertEqual(subs.list_id, ml_1 + ml_2)
# opt-out from opted-in mailing list + 1 non opted-in mailing list
(ml_2 + ml_3)._update_subscription_from_email(_email_formatted_upd, opt_out=True)
subs = self.env['mailing.subscription'].search(
[('contact_id', '=', contact.id)]
)
self.assertEqual(subs.list_id, ml_1 + ml_2)
|