287 lines
14 KiB
Python
287 lines
14 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
from freezegun import freeze_time
|
|
from markupsafe import Markup
|
|
from odoo.addons.whatsapp.tests.common import WhatsAppCommon, MockIncomingWhatsApp
|
|
from odoo.tests import tagged, users
|
|
|
|
|
|
@tagged('wa_message', 'discuss_channel')
|
|
class DiscussChannel(WhatsAppCommon, MockIncomingWhatsApp):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
cls.test_channel_wa, cls.test_channel_wa2, cls.test_channel_std = cls.env['discuss.channel'].create([
|
|
{
|
|
'channel_partner_ids': [(4, cls.user_wa_admin.partner_id.id)],
|
|
'channel_type': 'whatsapp',
|
|
'name': 'Dummy WA Channel',
|
|
'wa_account_id': cls.whatsapp_account.id,
|
|
'whatsapp_number': '911234567891',
|
|
'whatsapp_partner_id': cls.whatsapp_customer.id,
|
|
}, {
|
|
'channel_partner_ids': [(4, cls.user_wa_admin.partner_id.id)],
|
|
'channel_type': 'whatsapp',
|
|
'name': 'Dummy WA Channel 2',
|
|
'wa_account_id': cls.whatsapp_account.id,
|
|
'whatsapp_number': '911234567891',
|
|
'whatsapp_partner_id': cls.whatsapp_customer.id,
|
|
}, {
|
|
'channel_partner_ids': [(4, cls.user_wa_admin.partner_id.id)],
|
|
'channel_type': 'channel',
|
|
'name': 'Dummy Test Channel',
|
|
}
|
|
])
|
|
cls.channel_template = cls.env['whatsapp.template'].create({
|
|
"body": """Hello there,
|
|
Just a quick note to let you know that we're here to help with anything you might need. If you have any questions, please don't hesitate to send us a message.
|
|
We're always happy to assist!""",
|
|
"footer_text": "Write 'stop' to stop receiving messages",
|
|
"lang_code": "en",
|
|
"model_id": cls.env['ir.model']._get_id('discuss.channel'),
|
|
"phone_field": "whatsapp_number",
|
|
"status": "approved",
|
|
"template_name": "conversation_reviver",
|
|
"template_type": "marketing",
|
|
})
|
|
|
|
def test_gc_whatsapp_inactive(self):
|
|
for test_record, delay_days, mark_read in ((self.test_channel_wa, 2, True), (self.test_channel_wa2, 6, False)): # 2 days - 6 days
|
|
with self.subTest(test_record=test_record), self.mockWhatsappGateway():
|
|
test_record.channel_pin(pinned=True)
|
|
member_of_operator = self.env["discuss.channel.member"].search(
|
|
[
|
|
("channel_id", "=", test_record.id),
|
|
("partner_id", "=", self.user_wa_admin.partner_id.id),
|
|
]
|
|
)
|
|
message = test_record.message_post(
|
|
author_id=self.whatsapp_customer.id,
|
|
body='TestBody',
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
)
|
|
if mark_read:
|
|
member_of_operator._mark_as_read(message.id)
|
|
self.assertTrue(member_of_operator.is_pinned)
|
|
with freeze_time(datetime.now() + timedelta(days=delay_days)):
|
|
member_of_operator._gc_unpin_whatsapp_channels()
|
|
self.assertFalse(member_of_operator.is_pinned)
|
|
|
|
def test_post_with_audio_attachment(self):
|
|
test_cases = (
|
|
{
|
|
'body': '',
|
|
'attachment_ids': self.audio_attachment_wa_admin.ids,
|
|
'expected_message_count': 1,
|
|
'is_body_empty': True,
|
|
},
|
|
{
|
|
'body': Markup('<p><br></p>'),
|
|
'attachment_ids': self.audio_attachment_wa_admin.ids,
|
|
'expected_message_count': 1,
|
|
'is_body_empty': True,
|
|
},
|
|
{
|
|
'body': 'TestBody',
|
|
'attachment_ids': self.audio_attachment_wa_admin.ids,
|
|
'expected_message_count': 2,
|
|
'is_body_empty': False,
|
|
},
|
|
{
|
|
'body': 'TestBody',
|
|
'attachment_ids': (self.image_attachment_wa_admin + self.audio_attachment_wa_admin).ids,
|
|
'expected_message_count': 2,
|
|
'is_body_empty': False,
|
|
},
|
|
)
|
|
for test_case in test_cases:
|
|
body = test_case['body']
|
|
attachment_ids = test_case['attachment_ids']
|
|
expected_message_count = test_case['expected_message_count']
|
|
is_body_empty = test_case['is_body_empty']
|
|
expect_audio_attachment = self.audio_attachment_wa_admin.id in attachment_ids
|
|
expect_image_attachment = self.image_attachment_wa_admin.id in attachment_ids
|
|
|
|
with self.subTest(
|
|
body=body, image_attachment=expect_image_attachment, audio_attachment=expect_audio_attachment
|
|
):
|
|
with self.mockWhatsappGateway(), self.mock_mail_app():
|
|
return_message = self.test_channel_wa.message_post(
|
|
author_id=self.test_channel_wa.whatsapp_partner_id.id,
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
body=body,
|
|
attachment_ids=attachment_ids,
|
|
)
|
|
self.assertEqual(len(return_message), 1, "We expect one returned message when posting.")
|
|
if body:
|
|
self.assertIn(
|
|
body, return_message.body,
|
|
"Should return the message containing the body if two are created."
|
|
)
|
|
messages = self._new_msgs
|
|
|
|
self.assertEqual(len(messages), expected_message_count)
|
|
self.assertEqual(len(self._wa_msg_sent), expected_message_count)
|
|
self.assertEqual(messages.wa_message_ids.mapped('msg_uid'), self._wa_msg_sent)
|
|
|
|
if not is_body_empty:
|
|
body_message = messages[0]
|
|
self.assertIn(body, body_message.body)
|
|
if expect_image_attachment:
|
|
self.assertEqual(len(body_message.attachment_ids), 1)
|
|
self.assertEqual(body_message.attachment_ids.mimetype, 'image/jpeg')
|
|
if expect_audio_attachment:
|
|
audio_message = messages[expected_message_count - 1]
|
|
self.assertEqual(len(audio_message.attachment_ids), 1)
|
|
self.assertEqual(audio_message.attachment_ids.mimetype, 'audio/mpeg')
|
|
if is_body_empty:
|
|
self.assertNotIn('caption', self._wa_msg_sent_vals[expected_message_count - 1])
|
|
|
|
@users('user_wa_admin')
|
|
def test_post_with_outbound(self):
|
|
""" Test automatic whatsapp message creation when posting on a whatsapp
|
|
channel: should create an outbound wa message """
|
|
test_channel_wa = self.test_channel_wa.with_env(self.env)
|
|
with self.mockWhatsappGateway():
|
|
new_msg = test_channel_wa.message_post(
|
|
author_id=test_channel_wa.whatsapp_partner_id.id,
|
|
body=Markup('<p>Line 1<br>Line 2</p>'),
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
)
|
|
wa_message = new_msg.wa_message_ids
|
|
self.assertEqual(self._wa_msg_sent_vals[0]['body'], "Line 1\nLine 2", "Mismatch body in `send_vals`")
|
|
self.assertEqual(len(wa_message), 1)
|
|
self.assertEqual(wa_message.message_type, 'outbound')
|
|
self.assertEqual(wa_message.mobile_number, f'+{test_channel_wa.whatsapp_number}')
|
|
self.assertTrue(wa_message.msg_uid)
|
|
self.assertEqual(wa_message.state, 'sent')
|
|
self.assertEqual(wa_message.wa_account_id, self.test_channel_wa.wa_account_id)
|
|
|
|
# should not be supported on other channels / models
|
|
for test_record in (self.whatsapp_customer, self.test_channel_std):
|
|
with self.subTest(test_record=test_record), self.mockWhatsappGateway():
|
|
new_msg = test_record.message_post(
|
|
author_id=test_channel_wa.whatsapp_partner_id.id,
|
|
body='TestBody',
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
)
|
|
self.assertFalse(new_msg.wa_message_ids)
|
|
|
|
@users('user_wa_admin')
|
|
def test_post_reviver_template(self):
|
|
""" Test usage of reviver template - composer creates message on a channel
|
|
and we should not have twice the same message due to _send_message creating
|
|
messages """
|
|
template = self.channel_template.with_env(self.env)
|
|
channel = self.test_channel_wa.with_env(self.env)
|
|
composer = self._instanciate_wa_composer_from_records(
|
|
template, from_records=channel,
|
|
)
|
|
with self.mock_mail_app(), self.mockWhatsappGateway():
|
|
composer.action_send_whatsapp_template()
|
|
self.assertWAMessageFromRecord(
|
|
channel,
|
|
fields_values={
|
|
'mobile_number': '911234567891',
|
|
},
|
|
mail_message_values={
|
|
'subtype_id': self.env.ref('mail.mt_comment'), # should be linked to channel post directly
|
|
},
|
|
)
|
|
# created mail.message: one due to post, and no additional log, we don't need
|
|
# two messages on the same document
|
|
self.assertEqual(len(self._new_msgs), 1)
|
|
self.assertEqual(self._new_msgs.model, 'discuss.channel')
|
|
self.assertEqual(self._new_msgs.res_id, channel.id)
|
|
self.assertEqual(
|
|
self._new_msgs.body,
|
|
"<p>Hello there,<br>Just a quick note to let you know that we're here to help with anything you might need. "
|
|
"If you have any questions, please don't hesitate to send us a message.<br>We're always happy to assist!</p>")
|
|
|
|
@users('user_wa_admin')
|
|
def test_post_with_url_body_cleanup_for_duplicated_urls(self):
|
|
""" Test that the we won't send the same URL twice in the body of a message to whatsapp."""
|
|
test_channel = self.test_channel_wa.with_env(self.env)
|
|
|
|
input_body = Markup('<p>I love <a href="https://shin.com">https://shin.com</a> and <a href="https://chan.com">https://chan.com</a></p>')
|
|
expected_body = "I love https://shin.com and https://chan.com"
|
|
|
|
with self.mockWhatsappGateway():
|
|
test_channel.message_post(
|
|
author_id=self.user_wa_admin.partner_id.id,
|
|
body=input_body,
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
)
|
|
|
|
self.assertEqual(len(self._wa_msg_sent_vals), 1, "One message should have been sent.")
|
|
sent_body = self._wa_msg_sent_vals[0].get('body')
|
|
self.assertEqual(sent_body, expected_body, "The body should not contain duplicated urls.")
|
|
|
|
@users('user_wa_admin')
|
|
def test_post_with_whatsapp_inbound_msg_uid(self):
|
|
""" Test automatic whatsapp message creation when posting from whatsapp
|
|
specific controller """
|
|
test_channel_wa = self.test_channel_wa.with_env(self.env)
|
|
new_msg = test_channel_wa.message_post(
|
|
author_id=test_channel_wa.whatsapp_partner_id.id,
|
|
body='TestBody',
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
whatsapp_inbound_msg_uid='msg.uid.123456789',
|
|
)
|
|
wa_message = new_msg.wa_message_ids
|
|
self.assertEqual(len(wa_message), 1)
|
|
self.assertEqual(wa_message.message_type, 'inbound')
|
|
self.assertEqual(wa_message.mobile_number, f'+{test_channel_wa.whatsapp_number}')
|
|
self.assertEqual(wa_message.msg_uid, 'msg.uid.123456789')
|
|
self.assertEqual(wa_message.state, 'received')
|
|
self.assertEqual(wa_message.wa_account_id, self.test_channel_wa.wa_account_id)
|
|
|
|
# should not be supported on other channels / models
|
|
for test_record in (self.whatsapp_customer, self.test_channel_std):
|
|
with self.subTest(test_record=test_record):
|
|
with self.assertRaises(ValueError):
|
|
test_record.message_post(
|
|
author_id=test_channel_wa.whatsapp_partner_id.id,
|
|
body='TestBody',
|
|
message_type='whatsapp_message',
|
|
subtype_xmlid='mail.mt_comment',
|
|
whatsapp_inbound_msg_uid='msg.uid.123456789',
|
|
)
|
|
|
|
def test_parent_msg_receiver(self):
|
|
template = self.env['whatsapp.template'].create({
|
|
'body': 'Hello World',
|
|
'model_id': self.env['ir.model']._get_id('res.partner'),
|
|
'name': 'Test-basic',
|
|
'status': 'approved',
|
|
'wa_account_id': self.whatsapp_account.id,
|
|
})
|
|
test_partner = self.env['res.partner'].create({
|
|
'country_id': self.env.ref('base.be').id,
|
|
'phone': '+32455001122',
|
|
'name': 'Test Partner',
|
|
})
|
|
composer = self._instanciate_wa_composer_from_records(template, from_records=test_partner)
|
|
with self.mockWhatsappGateway():
|
|
msg = composer.action_send_whatsapp_template()
|
|
|
|
with self.mockWhatsappGateway():
|
|
self._receive_whatsapp_message(
|
|
self.whatsapp_account,
|
|
"Hello, it's reply",
|
|
test_partner.phone,
|
|
additional_message_values={
|
|
'context': {'id': msg.msg_uid},
|
|
},
|
|
)
|
|
self.assertEqual(self._new_wa_msg.mail_message_id.parent_id, msg.mail_message_id)
|