You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
9.8 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2017 Emanuel Cino - <ecino@compassion.ch>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import json
  5. import mock
  6. from odoo.tests.common import HttpCase
  7. from ..controllers.json_request import RESTJsonRequest
  8. mock_base_send = 'odoo.addons.mail.models.mail_mail.MailMail.send'
  9. mock_sendgrid_api_client = ('odoo.addons.mail_sendgrid.models.mail_mail'
  10. '.SendGridAPIClient')
  11. mock_sendgrid_send = ('odoo.addons.mail_sendgrid.models.mail_mail.'
  12. 'MailMail.send_sendgrid')
  13. mock_config = ('odoo.addons.mail_sendgrid.models.mail_mail.'
  14. 'config')
  15. mock_config_template = ('odoo.addons.mail_sendgrid.models.sendgrid_template.'
  16. 'config')
  17. mock_template_api_client = ('odoo.addons.mail_sendgrid.models.'
  18. 'sendgrid_template.sendgrid.SendGridAPIClient')
  19. mock_json_request = 'odoo.http.Root.get_request'
  20. def side_effect_json(http_request):
  21. return RESTJsonRequest(http_request)
  22. class FakeClient(object):
  23. """ Mock Sendgrid APIClient """
  24. status_code = 202
  25. body = 'ok'
  26. def __init__(self):
  27. self.client = self
  28. self.mail = self
  29. self.send = self
  30. def post(self, **kwargs):
  31. return self
  32. class FakeRequest(object):
  33. """ Simulate a Sendgrid JSON request """
  34. def __init__(self, data):
  35. self.jsonrequest = [data]
  36. class FakeTemplateClient(object):
  37. """ Simulate the Sendgrid Template api"""
  38. def __init__(self):
  39. self.client = self
  40. self.templates = self
  41. self.body = json.dumps({
  42. "templates": [{
  43. "id": "fake_id",
  44. "name": "Fake Template"
  45. }],
  46. "versions": [{
  47. "active": True,
  48. "html_content": "<h1>fake</h1>",
  49. "plain_content": "fake",
  50. }],
  51. })
  52. def get(self):
  53. return self
  54. def _(self, id):
  55. return self
  56. class TestMailSendgrid(HttpCase):
  57. def setUp(self):
  58. super(TestMailSendgrid, self).setUp()
  59. self.sendgrid_template = self.env['sendgrid.template'].create({
  60. 'name': 'Test Template',
  61. 'remote_id': 'a74795d7-f926-4bad-8e7a-ae95fabd70fc',
  62. 'html_content': u'<h1>Test Sendgrid</h1><%body%>{footer}'
  63. })
  64. self.mail_template = self.env['mail.template'].create({
  65. 'name': 'Test Template',
  66. 'model_id': self.env.ref('base.model_res_partner').id,
  67. 'subject': 'Test e-mail',
  68. 'body_html': u'Dear ${object.name}, hello!',
  69. 'sendgrid_template_ids': [
  70. (0, 0, {'lang': 'en_US', 'sendgrid_template_id':
  71. self.sendgrid_template.id})]
  72. })
  73. self.recipient = self.env.ref('base.partner_demo')
  74. self.mail_wizard = self.env['mail.compose.message'].create({
  75. 'template_id': self.mail_template.id,
  76. 'composition_mode': 'comment',
  77. 'model': 'res.partner',
  78. 'res_id': self.recipient.id
  79. }).with_context(active_id=self.recipient.id)
  80. self.mail_wizard.onchange_template_id_wrapper()
  81. self.timestamp = u'1471021089'
  82. self.event = {
  83. 'timestamp': self.timestamp,
  84. 'sg_event_id': u"f_JoKtrLQaOXUc4thXgROg",
  85. 'email': self.recipient.email,
  86. 'odoo_db': self.env.cr.dbname,
  87. 'odoo_id': u'<xxx.xxx.xxx-openerp-xxx-res.partner@test_db>'
  88. }
  89. self.metadata = {
  90. 'ip': '127.0.0.1',
  91. 'user_agent': False,
  92. 'os_family': False,
  93. 'ua_family': False,
  94. }
  95. self.request = FakeRequest(self.event)
  96. def create_email(self, vals=None):
  97. mail_vals = self.mail_wizard.get_mail_values(self.recipient.ids)[
  98. self.recipient.id]
  99. mail_vals['recipient_ids'] = [(6, 0, self.recipient.ids)]
  100. if vals is not None:
  101. mail_vals.update(vals)
  102. return self.env['mail.mail'].with_context(test_mode=True).create(
  103. mail_vals)
  104. def test_preview(self):
  105. """
  106. Test the preview email_template is getting the Sendgrid template
  107. """
  108. preview_wizard = self.env['email_template.preview'].with_context(
  109. template_id=self.mail_template.id,
  110. default_res_id=self.recipient.id
  111. ).create({})
  112. # For a strange reason, res_id is converted to string
  113. preview_wizard.res_id = self.recipient.id
  114. preview_wizard.on_change_res_id()
  115. self.assertIn(u'<h1>Test Sendgrid</h1>', preview_wizard.body_html)
  116. self.assertIn(self.recipient.name, preview_wizard.body_html)
  117. def test_substitutions(self):
  118. """ Test substitutions in templates. """
  119. self.assertEqual(self.sendgrid_template.detected_keywords, "{footer}")
  120. self.mail_template.update_substitutions()
  121. substitutions = self.mail_template.substitution_ids
  122. self.assertEqual(len(substitutions), 1)
  123. self.assertEqual(substitutions.key, '{footer}')
  124. def test_create_email(self):
  125. """ Test that Sendgrid template is pushed in e-mail. """
  126. self.mail_template.update_substitutions()
  127. mail_values = self.mail_wizard.get_mail_values(self.recipient.ids)[
  128. self.recipient.id]
  129. # Test Sendgrid HTML preview
  130. self.assertEqual(
  131. self.mail_wizard.body_sendgrid,
  132. self.sendgrid_template.html_content.replace(
  133. '<%body%>', mail_values['body'])
  134. )
  135. mail = self.env['mail.mail'].create(mail_values)
  136. self.assertEqual(mail.sendgrid_template_id.id,
  137. self.sendgrid_template.id)
  138. self.assertEqual(len(mail.substitution_ids), 1)
  139. @mock.patch(mock_base_send)
  140. @mock.patch(mock_sendgrid_send)
  141. def test_send_email_default(self, mock_sendgrid, mock_email):
  142. """ Tests that sending an e-mail by default doesn't use Sendgrid,
  143. and that Sendgrid is used when system parameter is set.
  144. """
  145. self.env['ir.config_parameter'].set_param(
  146. 'mail_sendgrid.send_method', False)
  147. mock_sendgrid.return_value = True
  148. mock_email.return_value = True
  149. mail = self.create_email()
  150. mail.send()
  151. self.assertTrue(mock_email.called)
  152. self.assertFalse(mock_sendgrid.called)
  153. self.env['ir.config_parameter'].set_param(
  154. 'mail_sendgrid.send_method', 'sendgrid')
  155. # Force again computation of send_method
  156. self.env.invalidate_all()
  157. mail.send()
  158. self.assertEqual(mock_email.call_count, 1)
  159. self.assertEqual(mock_sendgrid.call_count, 1)
  160. @mock.patch(mock_sendgrid_api_client)
  161. @mock.patch(mock_config)
  162. def test_mail_tracking(self, m_config, mock_sendgrid):
  163. """ Test various tracking events. """
  164. self.env['ir.config_parameter'].set_param(
  165. 'mail_sendgrid.send_method', 'sendgrid')
  166. mock_sendgrid.return_value = FakeClient()
  167. m_config.get.return_value = "ushuwejhfkj"
  168. # Send mail
  169. mail = self.create_email()
  170. mail.send()
  171. self.assertEqual(mock_sendgrid.called, True)
  172. self.assertEqual(mail.state, 'sent')
  173. mail_tracking = mail.tracking_email_ids
  174. self.assertEqual(len(mail_tracking), 1)
  175. self.assertFalse(mail_tracking.state)
  176. # Test mail processed
  177. self.event.update({
  178. 'event': u'processed',
  179. 'odoo_id': mail.message_id
  180. })
  181. response = self.env['mail.tracking.email'].event_process(
  182. self.request, self.event, self.metadata)
  183. self.assertEqual(response, 'OK')
  184. self.assertEqual(mail_tracking.state, 'sent')
  185. # Test mail delivered
  186. self.event['event'] = 'delivered'
  187. self.env['mail.tracking.email'].event_process(
  188. self.request, self.event, self.metadata)
  189. self.assertEqual(mail_tracking.state, 'delivered')
  190. self.assertEqual(mail_tracking.recipient, self.recipient.email)
  191. self.assertFalse(mail.opened)
  192. # Test mail opened
  193. self.event['event'] = 'open'
  194. self.env['mail.tracking.email'].event_process(
  195. self.request, self.event, self.metadata)
  196. self.assertEqual(mail_tracking.state, 'opened')
  197. self.assertTrue(mail.opened)
  198. # Test click e-mail
  199. self.event['event'] = 'click'
  200. self.env['mail.tracking.email'].event_process(
  201. self.request, self.event, self.metadata)
  202. self.assertEqual(mail_tracking.state, 'opened')
  203. self.assertEqual(mail.click_count, 1)
  204. # Test events are linked to e-mail
  205. self.assertEquals(len(mail.tracking_event_ids), 4)
  206. def test_controller(self):
  207. """ Check the controller is working """
  208. event_data = [self.event]
  209. with mock.patch(mock_json_request,
  210. side_effect=side_effect_json) as json_mock:
  211. json_mock.return_value = True
  212. result = self.url_open(
  213. '/mail/tracking/sendgrid/' + self.session.db,
  214. json.dumps(event_data)
  215. )
  216. self.assertTrue(json_mock.called)
  217. self.assertTrue(result)
  218. # Invalid request
  219. self.url_open(
  220. '/mail/tracking/sendgrid/' + self.session.db,
  221. "[{'invalid': True}]"
  222. )
  223. @mock.patch(mock_template_api_client)
  224. @mock.patch(mock_config_template)
  225. def test_update_templates(self, m_config, m_sendgrid):
  226. m_config.return_value = "ldkfjsOIWJRksfj"
  227. m_sendgrid.return_value = FakeTemplateClient()
  228. self.env['sendgrid.template'].update_templates()
  229. template = self.env['sendgrid.template'].search([
  230. ('remote_id', '=', 'fake_id')
  231. ])
  232. self.assertTrue(template)
  233. def tearDown(self):
  234. super(TestMailSendgrid, self).tearDown()
  235. self.env['ir.config_parameter'].set_param(
  236. 'mail_sendgrid.send_method', 'traditional')