Skip to content

Commit 80fb3cd

Browse files
committed
Almost everything is now covered by unittests except for all parts which really count
1 parent b1d38a4 commit 80fb3cd

File tree

3 files changed

+80
-35
lines changed

3 files changed

+80
-35
lines changed

projects/test_views.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
from unittest.mock import Mock, patch
2+
13
from authlib.little_auth.models import User
24
from django.test import Client, TestCase
35
from django.test.utils import override_settings
46

5-
from projects.models import Project
7+
from projects.models import Catalog, Project
8+
from projects.translators import TranslationError
69

710

811
class ProjectsTest(TestCase):
@@ -75,6 +78,11 @@ def test_smoke(self):
7578
)
7679
self.assertEqual(r.content.decode("utf-8"), c.pofile)
7780

81+
r = su_client.post(
82+
"/api/pofile/fr/djangojs/", headers={"x-project-token": p.token}
83+
)
84+
self.assertEqual(r.status_code, 405)
85+
7886
r = su_client.get(
7987
"/api/pofile/de/djangojs/", headers={"x-project-token": p.token}
8088
)
@@ -160,3 +168,36 @@ def test_smoke(self):
160168

161169
self.assertContains(r, '<td class="field-explicit_users">-</td>')
162170
self.assertContains(r, '<td class="field-explicit_users">use***@***.com</td>')
171+
172+
def test_suggest(self):
173+
c = Client()
174+
175+
r = c.get("/suggest/")
176+
self.assertEqual(r.status_code, 405)
177+
178+
r = c.post("/suggest/")
179+
self.assertEqual(r.status_code, 403)
180+
181+
user = User.objects.create_user("[email protected]", "user")
182+
c.force_login(user)
183+
184+
r = c.post("/suggest/")
185+
self.assertEqual(r.status_code, 400)
186+
187+
with patch(
188+
"projects.views.translators.translate_by_deepl", lambda *a: "Bonjour"
189+
):
190+
r = c.post("/suggest/", {"language_code": "fr", "msgid": "Anything"})
191+
self.assertEqual(r.status_code, 200)
192+
self.assertEqual(r.json(), {"msgstr": "Bonjour"})
193+
194+
mock = Mock()
195+
mock.side_effect = TranslationError("Oops")
196+
with patch("projects.views.translators.translate_by_deepl", mock):
197+
r = c.post("/suggest/", {"language_code": "fr", "msgid": "Anything"})
198+
self.assertEqual(r.status_code, 200)
199+
self.assertEqual(r.json(), {"error": "Oops"})
200+
201+
def test_invalid_catalog(self):
202+
c = Catalog(language_code="it", domain="django", pofile="blub")
203+
self.assertEqual(str(c), "Italian, django (Invalid)")

projects/translators.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import requests
2+
3+
4+
class TranslationError(Exception):
5+
pass
6+
7+
8+
def translate_by_deepl(text, to_language, auth_key):
9+
# Copied 1:1 from django-rosetta, thanks!
10+
if auth_key.lower().endswith(":fx"):
11+
endpoint = "https://api-free.deepl.com"
12+
else:
13+
endpoint = "https://api.deepl.com"
14+
15+
r = requests.post(
16+
f"{endpoint}/v2/translate",
17+
headers={"Authorization": f"DeepL-Auth-Key {auth_key}"},
18+
data={
19+
"target_lang": to_language.upper(),
20+
"text": text,
21+
},
22+
timeout=5,
23+
)
24+
if r.status_code != 200:
25+
raise TranslationError(
26+
f"Deepl response is {r.status_code}. Please check your API key or try again later."
27+
)
28+
try:
29+
return r.json().get("translations")[0].get("text")
30+
except Exception as exc:
31+
raise TranslationError(
32+
"Deepl returned a non-JSON or unexpected response."
33+
) from exc

projects/views.py

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import polib
2-
import requests
32
from django import forms, http
43
from django.conf import settings
54
from django.contrib.auth.decorators import login_required
@@ -9,8 +8,10 @@
98
from django.utils.timezone import localtime
109
from django.utils.translation import gettext_lazy as _
1110
from django.views.decorators.csrf import csrf_exempt
11+
from django.views.decorators.http import require_POST
1212

1313
from form_rendering import adapt_rendering
14+
from projects import translators
1415
from projects.models import Catalog, Project
1516

1617

@@ -235,42 +236,12 @@ def catalog(request, project, language_code, domain):
235236
)
236237

237238

238-
class TranslationError(Exception):
239-
pass
240-
241-
242-
def translate_by_deepl(text, to_language, auth_key):
243-
if auth_key.lower().endswith(":fx"):
244-
endpoint = "https://api-free.deepl.com"
245-
else:
246-
endpoint = "https://api.deepl.com"
247-
248-
r = requests.post(
249-
f"{endpoint}/v2/translate",
250-
headers={"Authorization": f"DeepL-Auth-Key {auth_key}"},
251-
data={
252-
"target_lang": to_language.upper(),
253-
"text": text,
254-
},
255-
timeout=5,
256-
)
257-
if r.status_code != 200:
258-
raise TranslationError(
259-
f"Deepl response is {r.status_code}. Please check your API key or try again later."
260-
)
261-
try:
262-
return r.json().get("translations")[0].get("text")
263-
except Exception as exc:
264-
raise TranslationError(
265-
"Deepl returned a non-JSON or unexpected response."
266-
) from exc
267-
268-
269239
class SuggestForm(forms.Form):
270240
language_code = forms.CharField()
271241
msgid = forms.CharField()
272242

273243

244+
@require_POST
274245
def suggest(request):
275246
if not request.user.is_authenticated:
276247
return http.HttpResponseForbidden()
@@ -279,10 +250,10 @@ def suggest(request):
279250
if form.is_valid():
280251
data = form.cleaned_data
281252
try:
282-
translation = translate_by_deepl(
253+
translation = translators.translate_by_deepl(
283254
data["msgid"], data["language_code"], settings.DEEPL_AUTH_KEY
284255
)
285-
except TranslationError as exc:
256+
except translators.TranslationError as exc:
286257
return http.JsonResponse({"error": str(exc)})
287258
return http.JsonResponse({"msgstr": translation})
288259

0 commit comments

Comments
 (0)