File: test_mail_message_translate.py

package info (click to toggle)
odoo 18.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 878,716 kB
  • sloc: javascript: 927,937; python: 685,670; xml: 388,524; sh: 1,033; sql: 415; makefile: 26
file content (131 lines) | stat: -rw-r--r-- 6,141 bytes parent folder | download
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
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import json
import requests
from http import HTTPStatus
from unittest.mock import patch

from odoo.addons.base.tests.common import HttpCaseWithUserDemo
from odoo.tests.common import JsonRpcException, new_test_user, tagged
from odoo.tools import mute_logger

SAMPLE = {
    "text": "<p>Al mal tiempo, buena cara.</p>",
    "src": "es",
    "en": "<p>To bad weather, good face.</p>",
    "fr": "<p>Au mauvais temps, bonne tĂȘte.</p>",
    "nl": "<script src='xss-min.js'/><p onclick='XSS()'>Bij slecht weer, goed gezicht.</p>",
    "lang": {
        "fr": "espagnol",
        "en": "Spanish",
    },
}


def mock_response(fun):
    def wrapper(self, url, data=False, params=False, timeout=5):
        response = requests.Response()
        response.status_code = HTTPStatus.OK
        content = {"data": fun(self, url=url, data=data, params=params)}
        if not content["data"]:
            response.status_code = HTTPStatus.BAD_REQUEST
            content = {"error": {"message": "Mocked Error"}}
        response._content = json.dumps(content).encode()
        return response

    return wrapper


# Google Cloud Translation Documentation: https://cloud.google.com/translate/docs/reference/api-overview?hl=en
@tagged("post_install", "-at_install", "mail_message")
class TestTranslationController(HttpCaseWithUserDemo):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.env["res.lang"]._activate_lang("fr_FR")
        cls.env["res.lang"]._activate_lang("en_US")
        cls.env.ref("base.user_admin").write({"lang": "fr_FR"})
        cls.api_key = "VALIDKEY"
        cls.env["ir.config_parameter"].set_param("mail.google_translate_api_key", cls.api_key)
        cls.message = cls.env["mail.message"].create(
            {
                "body": SAMPLE["text"],
                "model": "res.partner",
                "res_id": cls.env.ref("base.user_admin").partner_id.id,
                "message_type": "comment",
            }
        )
        cls.request_count = 0

    @mock_response
    def _patched_post(self, url, data, params, timeout=5):
        self.request_count += 1
        if f"/v2/detect?key={self.api_key}" in url:
            result = {
                "language": SAMPLE["src"],
                "isReliable": True,
                "confidence": 0.98,
            }
            return {"detections": [[result]]}
        if f"/v2/?key={self.api_key}" in url:
            return {"translations": [{"translatedText": SAMPLE[data.get("target")]}]}

    def _mock_translation_request(self, data):
        with patch.object(requests, "post", self._patched_post):
            return self.make_jsonrpc_request("/mail/message/translate", data)

    def test_update_message(self):
        self.authenticate("admin", "admin")
        result = self._mock_translation_request({"message_id": self.message.id})
        self.assertFalse(result.get("error"))
        self.assertEqual(self.env["mail.message.translation"].search_count([]), 1)
        # The translation records should not be discarded if the body did not change.
        self.make_jsonrpc_request(
            "/mail/message/update_content", {"message_id": self.message.id, "body": None, "attachment_ids": []}
        )
        self.assertEqual(self.env["mail.message.translation"].search_count([]), 1)
        self.make_jsonrpc_request(
            "/mail/message/update_content", {"message_id": self.message.id, "body": "update", "attachment_ids": []}
        )
        self.assertFalse(self.env["mail.message.translation"].search_count([]))

    def test_translation_multi_users(self):
        new_test_user(self.env, "user_test_fr", groups="base.group_user", lang="fr_FR")
        new_test_user(self.env, "user_test_en", groups="base.group_user", lang="en_US")
        for login, target_lang in [("user_test_fr", "fr"), ("user_test_en", "en"), ("admin", "fr")]:
            self.authenticate(login, login)
            result = self._mock_translation_request({"message_id": self.message.id})
            self.assertFalse(result.get("error"))
            self.assertEqual(result["body"], SAMPLE[target_lang])
            self.assertEqual(result["lang_name"], SAMPLE["lang"][target_lang])
        # There is one translation record per target language.
        self.assertEqual(self.env["mail.message.translation"].search_count([]), 2)
        # No API request should be sent if a translation value or source already exists.
        self.assertEqual(self.request_count, 3)

    def test_invalid_api_key(self):
        self.env["ir.config_parameter"].set_param("mail.google_translate_api_key", "INVALIDKEY")
        self.authenticate("demo", "demo")
        result = self._mock_translation_request({"message_id": self.message.id})
        self.assertNotIn("body", result)
        self.assertNotIn("lang_name", result)
        self.assertTrue(result["error"])

    def test_html_sanitization(self):
        self.env["res.lang"]._activate_lang("nl_NL")
        new_test_user(self.env, "user_test_nl", groups="base.group_user", lang="nl_NL")
        self.authenticate("user_test_nl", "user_test_nl")
        result = self._mock_translation_request({"message_id": self.message.id})
        self.assertFalse(result.get("error"))
        self.assertHTMLEqual(result["body"], "<p>Bij slecht weer, goed gezicht.</p>")
        translation = self.env["mail.message.translation"].search([])
        self.assertEqual(len(translation), 1)
        self.assertHTMLEqual(translation.body, "<p>Bij slecht weer, goed gezicht.</p>")

    def test_access_right(self):
        with self.assertRaises(JsonRpcException, msg="odoo.http.SessionExpiredException"):
            self._mock_translation_request({"message_id": self.message.id})
        new_test_user(self.env, "user_test_portal", groups="base.group_portal", lang="fr_FR")
        self.authenticate("user_test_portal", "user_test_portal")
        with self.assertRaises(JsonRpcException, msg="odoo.exceptions.AccessError"), mute_logger("odoo.http"):
            self._mock_translation_request({"message_id": self.message.id})