Before this commit, in gateway tools, we used to consider URL as a shortened which was having `/r` in it. However this is not true in all cases. Any random URL can have `/r` in it but it might not be a shortened one. It caused random failures on runbot time to time. This commit makes a bit precise search (`/r/`) to consider URL as a shortened one and thus avoiding those random test failures on the runbot. TaskID - 2276386 closes odoo/odoo#54944 X-original-commit: b8045b49d0693292e6240dfb3acd7c9a6450ad77 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
109 lines
4.8 KiB
Python
109 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import re
|
|
import werkzeug
|
|
|
|
from odoo import tools
|
|
from odoo.addons.mass_mailing.tests.common import MassMailCommon
|
|
from odoo.addons.sms.tests.common import SMSCase, SMSCommon
|
|
|
|
|
|
class MassSMSCase(SMSCase):
|
|
|
|
# ------------------------------------------------------------
|
|
# GATEWAY TOOLS
|
|
# ------------------------------------------------------------
|
|
|
|
def gateway_sms_click(self, sent_sms):
|
|
""" Simulate a click on a sent SMS. Usage: giving a partner and/or
|
|
a number, find an SMS sent to him, find shortened links in its body
|
|
and call add_click to simulate a click. """
|
|
for url in re.findall(tools.TEXT_URL_REGEX, sent_sms['body']):
|
|
if '/r/' in url: # shortened link, like 'http://localhost:8069/r/LBG/s/53'
|
|
parsed_url = werkzeug.urls.url_parse(url)
|
|
path_items = parsed_url.path.split('/')
|
|
code, sms_sms_id = path_items[2], int(path_items[4])
|
|
trace_id = self.env['mailing.trace'].sudo().search([('sms_sms_id_int', '=', sms_sms_id)]).id
|
|
|
|
self.env['link.tracker.click'].sudo().add_click(
|
|
code,
|
|
ip='100.200.300.400',
|
|
country_code='BE',
|
|
mailing_trace_id=trace_id
|
|
)
|
|
|
|
|
|
# ------------------------------------------------------------
|
|
# ASSERTS
|
|
# ------------------------------------------------------------
|
|
|
|
def assertSMSOutgoingStatistics(self, partners, numbers, records, mailing):
|
|
found_sms = self.env['sms.sms'].sudo().search([
|
|
'|', ('partner_id', 'in', partners.ids), ('number', 'in', numbers),
|
|
('state', '=', 'outgoing')
|
|
])
|
|
self.assertEqual(found_sms.filtered(lambda s: s.partner_id).mapped('partner_id'), partners)
|
|
self.assertEqual(set(found_sms.filtered(lambda s: not s.partner_id).mapped('number')), set(numbers))
|
|
|
|
found_traces = self.env['mailing.trace'].sudo().search([
|
|
('sms_sms_id_int', 'in', found_sms.ids),
|
|
])
|
|
self.assertEqual(len(found_sms), len(found_traces))
|
|
self.assertTrue(all(s.state == 'outgoing' for s in found_traces))
|
|
self.assertTrue(all(s.res_model == records._name for s in found_traces))
|
|
self.assertEqual(set(found_traces.mapped('res_id')), set(records.ids))
|
|
self.assertTrue(all(s.mass_mailing_id == mailing for s in found_traces))
|
|
|
|
def assertSMSStatistics(self, recipients_info, mailing, records, check_sms=True):
|
|
""" Check content of notifications.
|
|
|
|
:param recipients_info: list[{
|
|
'partner': res.partner record (may be empty),
|
|
'number': number used for notification (may be empty, computed based on partner),
|
|
'state': outgoing / sent / ignored / exception / opened (sent by default),
|
|
'record: linked record,
|
|
'content': optional: if set, check content of sent SMS
|
|
'failure_type': optional: sms_number_missing / sms_number_format / sms_credit / sms_server
|
|
},
|
|
{ ... }
|
|
]
|
|
"""
|
|
traces = self.env['mailing.trace'].search([
|
|
('mass_mailing_id', 'in', mailing.ids),
|
|
('res_id', 'in', records.ids)
|
|
])
|
|
|
|
self.assertTrue(all(s.model == records._name for s in traces))
|
|
# self.assertTrue(all(s.utm_campaign_id == mailing.campaign_id for s in traces))
|
|
self.assertEqual(set(s.res_id for s in traces), set(records.ids))
|
|
|
|
for recipient_info in recipients_info:
|
|
partner = recipient_info.get('partner', self.env['res.partner'])
|
|
number = recipient_info.get('number')
|
|
state = recipient_info.get('state', 'outgoing')
|
|
content = recipient_info.get('content', None)
|
|
if number is None and partner:
|
|
number = partner._sms_get_recipients_info()[partner.id]['sanitized']
|
|
|
|
notif = traces.filtered(lambda s: s.sms_number == number and s.state == state)
|
|
self.assertTrue(notif, 'SMS: not found notification for number %s, (state: %s)' % (number, state))
|
|
|
|
if check_sms:
|
|
if state == 'sent':
|
|
self.assertSMSSent([number], content)
|
|
elif state == 'outgoing':
|
|
self.assertSMSOutgoing(partner, number, content)
|
|
elif state == 'exception':
|
|
self.assertSMSFailed(partner, number, recipient_info.get('failure_type'), content)
|
|
elif state == 'ignored':
|
|
self.assertSMSCanceled(partner, number, recipient_info.get('failure_type', False), content)
|
|
else:
|
|
raise NotImplementedError()
|
|
|
|
|
|
class MassSMSCommon(MassMailCommon, SMSCommon, MassSMSCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(MassSMSCommon, cls).setUpClass()
|