303 lines
13 KiB
Python
303 lines
13 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import json
|
|
import socket
|
|
import urllib.parse
|
|
|
|
import odoo
|
|
from odoo.addons.mail.tests.common import mail_new_test_user
|
|
from odoo.addons.sms.tests.common import SMSCommon
|
|
from odoo.addons.test_mail.data.test_mail_data import MAIL_TEMPLATE
|
|
from odoo.tests import tagged
|
|
from markupsafe import Markup
|
|
from unittest.mock import patch
|
|
|
|
|
|
@tagged('mail_push')
|
|
class TestMailMobile(SMSCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(TestMailMobile, cls).setUpClass()
|
|
cls.original_domain = cls.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
|
cls.env['ir.config_parameter'].sudo().set_param('web.base.url', 'http://yourcompany.odoo.com')
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
cls.env['ir.config_parameter'].sudo().set_param('web.base.url', cls.original_domain)
|
|
super(TestMailMobile, cls).tearDownClass()
|
|
|
|
def test_override_url_in_mail(self):
|
|
url = self.env['mail.thread']._notify_get_action_link('view', model='mail.activity', res_id=1)
|
|
original_expected_link = 'http://yourcompany.odoo.com/mail/view?model=mail.activity&res_id=1'
|
|
expected_url = 'https://redirect-url.email/?link={0}&apn={1}&afl={0}&ibi={1}&ifl={0}'.format(
|
|
urllib.parse.quote(original_expected_link, safe=''),
|
|
'com.odoo.mobile',
|
|
)
|
|
self.assertEqual(url, expected_url)
|
|
|
|
def test_blacklist_not_override_url_in_mail(self):
|
|
url = self.env['mail.thread']._notify_get_action_link('view', model='mail.activity', res_id=1, access_token='test')
|
|
self.assertFalse(url.startswith('https://redirect-url.email/'))
|
|
|
|
|
|
@tagged('post_install', '-at_install', 'mail_push')
|
|
class TestPushNotification(SMSCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(TestPushNotification, cls).setUpClass()
|
|
sudo_icp = cls.env['ir.config_parameter'].sudo()
|
|
sudo_icp.set_param('odoo_ocn.project_id', 'Test')
|
|
sudo_icp.set_param('mail_mobile.enable_ocn', True)
|
|
|
|
channel = cls.env['discuss.channel'].with_context(cls._test_context)
|
|
|
|
cls.user_email = cls.user_employee
|
|
cls.user_email.notification_type = 'email'
|
|
cls.user_email.partner_id.ocn_token = 'Test OCN Email'
|
|
|
|
cls.user_inbox = mail_new_test_user(
|
|
cls.env, login='user_inbox', groups='base.group_user', name='User Inbox',
|
|
notification_type='inbox'
|
|
)
|
|
cls.user_inbox.partner_id.ocn_token = 'Test OCN Inbox'
|
|
|
|
cls.record_simple = cls.env['mail.test.simple'].with_context(cls._test_context).create({
|
|
'name': 'Test',
|
|
'email_from': 'ignasse@example.com'
|
|
})
|
|
cls.record_simple.message_subscribe(partner_ids=[
|
|
cls.user_email.partner_id.id,
|
|
cls.user_inbox.partner_id.id,
|
|
])
|
|
cls.alias_gateway = cls.env['mail.alias'].create({
|
|
'alias_contact': 'everyone',
|
|
'alias_domain': cls.mail_alias_domain.id,
|
|
'alias_model_id': cls.env['ir.model']._get_id('mail.test.gateway.company'),
|
|
'alias_name': 'alias.gateway',
|
|
})
|
|
|
|
cls.direct_message_channel = channel.with_user(cls.user_email).create({
|
|
'channel_partner_ids': [
|
|
(4, cls.user_email.partner_id.id),
|
|
(4, cls.user_inbox.partner_id.id),
|
|
],
|
|
'channel_type': 'chat',
|
|
'name': "Direct Message",
|
|
})
|
|
|
|
cls.group_channel = cls.env['discuss.channel']._create_channel(name='Channel', group_id=None)
|
|
cls.group_channel._add_members(users=cls.user_email | cls.user_inbox)
|
|
|
|
@patch('odoo.addons.mail_mobile.models.mail_thread.iap_jsonrpc')
|
|
def test_push_notifications(self, jsonrpc):
|
|
# Test No Inbox Condition
|
|
self.record_simple.with_user(self.user_inbox).message_notify(
|
|
partner_ids=self.user_email.partner_id.ids,
|
|
body="Test",
|
|
subject="Test Activity",
|
|
)
|
|
jsonrpc.assert_not_called()
|
|
|
|
self.record_simple.with_user(self.user_email).message_notify(
|
|
partner_ids=self.user_inbox.partner_id.ids,
|
|
body="Test message send via OCN",
|
|
subject="Test Activity",
|
|
)
|
|
jsonrpc.assert_called_once()
|
|
self.assertEqual(jsonrpc.call_args[1]['params']['data']['model'], 'mail.test.simple')
|
|
self.assertEqual(jsonrpc.call_args[1]['params']['data']['res_id'], self.record_simple.id)
|
|
self.assertEqual(jsonrpc.call_args[1]['params']['data']['author_name'], self.user_email.name)
|
|
self.assertIn(
|
|
"Test message send via OCN",
|
|
jsonrpc.call_args[1]['params']['data']['body'],
|
|
'The body must be "Test message send via OCN"'
|
|
)
|
|
|
|
# Reset the mock counter
|
|
jsonrpc.reset_mock()
|
|
|
|
# Test Tracking Message
|
|
mail_test_ticket = self.env['mail.test.ticket'].with_context(self._test_context)
|
|
record_full = mail_test_ticket.with_user(self.user_email).create({
|
|
'name': 'Test',
|
|
})
|
|
record_full = record_full.with_context(mail_notrack=False)
|
|
|
|
container = self.env['mail.test.container'].create({'name': 'Container'})
|
|
record_full.message_subscribe(
|
|
partner_ids=[self.user_email.partner_id.id],
|
|
subtype_ids=[self.env.ref('test_mail.st_mail_test_ticket_container_upd').id],
|
|
)
|
|
record_full.write({
|
|
'name': 'Test2',
|
|
'email_from': 'noone@example.com',
|
|
'container_id': container.id,
|
|
})
|
|
self.flush_tracking()
|
|
jsonrpc.assert_not_called()
|
|
|
|
container2 = self.env['mail.test.container'].create({'name': 'Container Two'})
|
|
record_full.message_subscribe(
|
|
partner_ids=[self.user_inbox.partner_id.id],
|
|
subtype_ids=[self.env.ref('test_mail.st_mail_test_ticket_container_upd').id],
|
|
)
|
|
record_full.write({
|
|
'name': 'Test3',
|
|
'email_from': 'noone@example.com',
|
|
'container_id': container2.id,
|
|
})
|
|
self.flush_tracking()
|
|
jsonrpc.assert_called_once()
|
|
# As the tracking values are converted to text. We check the '→' added by ocn_client.
|
|
self.assertIn(
|
|
'→',
|
|
jsonrpc.call_args[1]['params']['data']['body'],
|
|
'No Tracking Message found'
|
|
)
|
|
|
|
@patch('odoo.addons.mail_mobile.models.mail_thread.iap_jsonrpc')
|
|
def test_push_notifications_android_channel(self, jsonrpc):
|
|
# Test Direct Message
|
|
self.direct_message_channel.with_user(self.user_email).message_post(
|
|
body="Test", message_type='comment', subtype_xmlid='mail.mt_comment')
|
|
self.assertEqual(
|
|
jsonrpc.call_args[1]['params']['data']['android_channel_id'],
|
|
'DirectMessage',
|
|
'The type of Android channel must be DirectMessage'
|
|
)
|
|
# FIXME: mobile apps use old "mail.channel" and cannot be changed on iOS
|
|
self.assertEqual(
|
|
jsonrpc.call_args[1]['params']['data']['model'],
|
|
'mail.channel',
|
|
'The model must be mail.channel (for Mobile App)'
|
|
)
|
|
|
|
# Reset the mock counter
|
|
jsonrpc.reset_mock()
|
|
|
|
# Test Following Message
|
|
self.record_simple.with_user(self.user_email).message_post(
|
|
body="Test", message_type='comment', subtype_xmlid="mail.mt_comment"
|
|
)
|
|
self.assertEqual(
|
|
jsonrpc.call_args[1]['params']['data']['android_channel_id'],
|
|
'Following',
|
|
'The type of Android channel must be Following'
|
|
)
|
|
|
|
# Reset the mock counter
|
|
jsonrpc.reset_mock()
|
|
|
|
# Test Channel Message
|
|
self.group_channel.with_user(self.user_email).message_post(
|
|
body="Test", partner_ids=self.user_inbox.partner_id.ids,
|
|
message_type='comment', subtype_xmlid='mail.mt_comment')
|
|
self.assertEqual(
|
|
jsonrpc.call_args[1]['params']['data']['android_channel_id'],
|
|
'ChannelMessage',
|
|
'The type of Android channel must be ChannelMessage'
|
|
)
|
|
|
|
# Reset the mock counter
|
|
jsonrpc.reset_mock()
|
|
|
|
# Test AtMention Message
|
|
self.record_simple.with_user(self.user_email).message_post(
|
|
body=Markup('<a href="/odoo" data-oe-id="%i" data-oe-model="res.partner" >@user</a>') %
|
|
self.user_inbox.partner_id.id,
|
|
message_type='comment', subtype_xmlid="mail.mt_comment"
|
|
)
|
|
self.assertEqual(
|
|
jsonrpc.call_args[1]['params']['data']['android_channel_id'],
|
|
'AtMention',
|
|
'The type of Android channel must be AtMention'
|
|
)
|
|
|
|
@patch('odoo.addons.mail_mobile.models.mail_thread.iap_jsonrpc')
|
|
def test_push_notifications_mail_replay(self, jsonrpc):
|
|
with self.mock_mail_gateway():
|
|
test_record = self.format_and_process(
|
|
MAIL_TEMPLATE, self.user_email.email_formatted,
|
|
f'{self.alias_gateway.display_name}, {self.user_inbox.email_formatted}',
|
|
subject='Test Record Creation',
|
|
target_model='mail.test.gateway.company',
|
|
)
|
|
self.assertEqual(len(test_record.message_ids), 1)
|
|
self.assertEqual(test_record.message_partner_ids, self.user_email.partner_id)
|
|
test_record.message_subscribe(partner_ids=[self.user_inbox.partner_id.id])
|
|
|
|
for include_as_external, has_notif in ((False, True), (True, False)):
|
|
with self.mock_mail_gateway():
|
|
to = f'{self.alias_gateway.display_name}'
|
|
if include_as_external:
|
|
to += f', {self.user_inbox.email_formatted}'
|
|
self.format_and_process(
|
|
MAIL_TEMPLATE, self.user_email.email_formatted, to,
|
|
subject='Repy By Email',
|
|
extra='In-Reply-To:\r\n\t%s\n' % test_record.message_ids[-1].message_id,
|
|
)
|
|
if has_notif:
|
|
# user_inbox is notified by Odoo, hence receives a push notification
|
|
jsonrpc.assert_called_once()
|
|
self.assertEqual(jsonrpc.call_args[1]['params']['data']['author_name'], self.user_email.name)
|
|
self.assertIn(
|
|
"Please call me as soon as possible this afternoon!\n\n--\nSylvie",
|
|
jsonrpc.call_args[1]['params']['data']['body'],
|
|
'The body must contain the text send by mail'
|
|
)
|
|
else:
|
|
jsonrpc.assert_not_called()
|
|
jsonrpc.reset_mock()
|
|
|
|
@patch('odoo.addons.mail_mobile.models.mail_thread.iap_jsonrpc')
|
|
@patch.object(odoo.addons.mail.models.mail_thread, 'push_to_end_point')
|
|
def test_push_notifications_whatsapp(self, push_to_end_point, iap_jsonrpc):
|
|
"""
|
|
Verifies that the system correctly triggers web push notifications upon posting a WhatsApp message.
|
|
Notifications can either be sent immediately or scheduled via cron.
|
|
At the time this test was written, notifications are sent directly if the number of recipient devices is fewer than MAX_DIRECT_PUSH.
|
|
"""
|
|
|
|
self.env['mail.push.device'].get_web_push_vapid_public_key()
|
|
self.vapid_public_key = self.env['mail.push.device'].get_web_push_vapid_public_key()
|
|
mail_push_device = self.env['mail.push.device'].sudo().create([{
|
|
'endpoint': 'https://test.odoo.com/webpush/user1',
|
|
'expiration_time': None,
|
|
'keys': json.dumps({
|
|
'p256dh': 'BGbhnoP_91U7oR59BaaSx0JnDv2oEooYnJRV2AbY5TBeKGCRCf0HcIJ9bOKchUCDH4cHYWo9SYDz3U-8vSxPL_A',
|
|
'auth': 'DJFdtAgZwrT6yYkUMgUqow'
|
|
}),
|
|
'partner_id': self.user_inbox.partner_id.id,
|
|
}])
|
|
|
|
self.direct_message_channel.with_user(self.user_email).message_post(
|
|
body=('This whatsapp message should generate web push notification'),
|
|
message_type='whatsapp_message', subtype_xmlid='mail.mt_comment'
|
|
)
|
|
self.assertEqual(self.env['mail.push'].search_count([]), 0,
|
|
'Notification scheduled with cron, expected only direct notification')
|
|
self.assertEqual(push_to_end_point.call_args.kwargs.get('device')['id'], mail_push_device.id,
|
|
'Web push notification (from whatsapp_message) was not sent to the right device')
|
|
push_to_end_point.assert_called_once()
|
|
push_to_end_point.reset_mock()
|
|
|
|
self.direct_message_channel.with_user(self.user_email).message_post(
|
|
body=('This comment message should generate any web push notifications'),
|
|
message_type='comment', subtype_xmlid='mail.mt_comment'
|
|
)
|
|
self.assertEqual(self.env['mail.push'].search_count([]), 0,
|
|
'Notification scheduled with cron, expected only direct notification')
|
|
self.assertEqual(push_to_end_point.call_args.kwargs.get('device')['id'], mail_push_device.id,
|
|
'Web push notification (from comment) was not sent to the right device')
|
|
push_to_end_point.assert_called_once()
|
|
push_to_end_point.reset_mock()
|
|
|
|
self.direct_message_channel.with_user(self.user_email).message_post(
|
|
body=('This email message should not generate any web push notifications'),
|
|
message_type='email', subtype_xmlid='mail.mt_comment'
|
|
)
|
|
self.assertFalse(push_to_end_point.called, 'Email message should not generate any web push notifications')
|