|
21 | 21 | from botocore.stub import ANY, Stubber |
22 | 22 | from django.core.management import call_command |
23 | 23 | from django.core.management.base import CommandError |
24 | | -from django.test import TestCase |
| 24 | +from django.test import SimpleTestCase, TestCase |
25 | 25 | from django.urls import reverse |
26 | 26 | from google.api_core import exceptions as google_api_exceptions |
27 | 27 | from google.cloud.translate import ( |
@@ -2972,6 +2972,20 @@ def test_exists(self) -> None: |
2972 | 2972 | results = machine.translate(unit, self.user) |
2973 | 2973 | self.assertNotEqual(results, []) |
2974 | 2974 |
|
| 2975 | + @patch("weblate.machinery.weblatetm.adjust_similarity_threshold") |
| 2976 | + def test_matches_still_probe_fuzzy_lookup(self, adjust_threshold) -> None: |
| 2977 | + unit = Unit.objects.filter(translation__language_code="cs")[0] |
| 2978 | + other = unit.translation.unit_set.exclude(pk=unit.pk)[0] |
| 2979 | + other.source = unit.source |
| 2980 | + other.target = "Preklad" |
| 2981 | + other.state = STATE_TRANSLATED |
| 2982 | + other.save() |
| 2983 | + |
| 2984 | + machine = WeblateTranslation({}) |
| 2985 | + machine.translate(unit, self.user) |
| 2986 | + |
| 2987 | + adjust_threshold.assert_called_once_with(0.98) |
| 2988 | + |
2975 | 2989 |
|
2976 | 2990 | class CyrTranslitTranslationTest(ViewTestCase, BaseMachineTranslationTest): |
2977 | 2991 | ENGLISH = "sr@latin" |
@@ -3318,6 +3332,184 @@ def test_configure_invalid(self) -> None: |
3318 | 3332 | ) |
3319 | 3333 |
|
3320 | 3334 |
|
| 3335 | +class WeblateTranslationLookupTest(SimpleTestCase): |
| 3336 | + @patch("weblate.machinery.weblatetm.Unit.objects") |
| 3337 | + @patch("weblate.machinery.weblatetm.Translation.objects") |
| 3338 | + def test_get_base_queryset_uses_translation_subquery( |
| 3339 | + self, translation_objects, unit_objects |
| 3340 | + ) -> None: |
| 3341 | + machine = WeblateTranslation({}) |
| 3342 | + user = MagicMock() |
| 3343 | + translations_using = MagicMock() |
| 3344 | + translations = MagicMock() |
| 3345 | + filtered_translations = MagicMock() |
| 3346 | + translation_ids = MagicMock() |
| 3347 | + units_using = MagicMock() |
| 3348 | + queryset = MagicMock() |
| 3349 | + |
| 3350 | + translation_objects.using.return_value = translations_using |
| 3351 | + translations_using.all.return_value = translations |
| 3352 | + translations.filter_access.return_value = filtered_translations |
| 3353 | + filtered_translations.filter.return_value = translation_ids |
| 3354 | + translation_ids.values.return_value = "translation-subquery" |
| 3355 | + unit_objects.using.return_value = units_using |
| 3356 | + units_using.filter.return_value = queryset |
| 3357 | + |
| 3358 | + result = machine.get_base_queryset(user, "en", "cs") |
| 3359 | + |
| 3360 | + self.assertEqual(result, queryset) |
| 3361 | + translation_objects.using.assert_called_once_with("default") |
| 3362 | + translations.filter_access.assert_called_once_with(user) |
| 3363 | + filtered_translations.filter.assert_called_once_with( |
| 3364 | + component__source_language="en", |
| 3365 | + language="cs", |
| 3366 | + ) |
| 3367 | + translation_ids.values.assert_called_once_with("id") |
| 3368 | + unit_objects.using.assert_called_once_with("default") |
| 3369 | + units_using.filter.assert_called_once_with( |
| 3370 | + state__gte=STATE_TRANSLATED, |
| 3371 | + translation_id__in="translation-subquery", |
| 3372 | + ) |
| 3373 | + |
| 3374 | + @patch("weblate.machinery.weblatetm.adjust_similarity_threshold") |
| 3375 | + def test_get_matching_units_uses_fuzzy_lookup(self, adjust_threshold) -> None: |
| 3376 | + machine = WeblateTranslation({}) |
| 3377 | + base = MagicMock() |
| 3378 | + queryset = MagicMock() |
| 3379 | + annotated_queryset = MagicMock() |
| 3380 | + ordered_queryset = MagicMock() |
| 3381 | + prepared_queryset = MagicMock() |
| 3382 | + fuzzy_match = MagicMock(pk=1) |
| 3383 | + base.filter.return_value = queryset |
| 3384 | + queryset.annotate.return_value = annotated_queryset |
| 3385 | + annotated_queryset.order_by.return_value = ordered_queryset |
| 3386 | + prepared_queryset.iterator.return_value = [fuzzy_match] |
| 3387 | + |
| 3388 | + with patch.object( |
| 3389 | + machine, "prepare_queryset", return_value=prepared_queryset |
| 3390 | + ) as prepare_queryset: |
| 3391 | + results = machine.get_matching_units(base, "Hello", 75) |
| 3392 | + |
| 3393 | + self.assertEqual(results, [fuzzy_match]) |
| 3394 | + base.filter.assert_called_once_with(source__trgm_search="Hello") |
| 3395 | + queryset.annotate.assert_called_once() |
| 3396 | + annotated_queryset.order_by.assert_called_once_with("-match_similarity", "pk") |
| 3397 | + prepare_queryset.assert_called_once_with(ordered_queryset) |
| 3398 | + prepared_queryset.iterator.assert_called_once_with( |
| 3399 | + chunk_size=machine.candidate_limit |
| 3400 | + ) |
| 3401 | + adjust_threshold.assert_called_once_with(0.98) |
| 3402 | + |
| 3403 | + @patch("weblate.machinery.weblatetm.adjust_similarity_threshold") |
| 3404 | + def test_get_matching_units_orders_short_queries_before_slicing( |
| 3405 | + self, adjust_threshold |
| 3406 | + ) -> None: |
| 3407 | + machine = WeblateTranslation({}) |
| 3408 | + base = MagicMock() |
| 3409 | + short_queryset = MagicMock() |
| 3410 | + prepared_queryset = MagicMock() |
| 3411 | + fuzzy_match = MagicMock(pk=1) |
| 3412 | + prepared_queryset.iterator.return_value = [fuzzy_match] |
| 3413 | + |
| 3414 | + with ( |
| 3415 | + patch.object( |
| 3416 | + machine, "get_short_query_matches", return_value=short_queryset |
| 3417 | + ) as get_short_query_matches, |
| 3418 | + patch.object( |
| 3419 | + machine, "prepare_queryset", return_value=prepared_queryset |
| 3420 | + ) as prepare_queryset, |
| 3421 | + ): |
| 3422 | + results = machine.get_matching_units(base, "id", 75) |
| 3423 | + |
| 3424 | + self.assertEqual(results, [fuzzy_match]) |
| 3425 | + get_short_query_matches.assert_called_once_with(base, "id") |
| 3426 | + prepare_queryset.assert_called_once_with(short_queryset) |
| 3427 | + prepared_queryset.iterator.assert_called_once_with( |
| 3428 | + chunk_size=machine.candidate_limit |
| 3429 | + ) |
| 3430 | + adjust_threshold.assert_called_once_with(0.98) |
| 3431 | + |
| 3432 | + @patch("weblate.machinery.weblatetm.adjust_similarity_threshold") |
| 3433 | + def test_get_matching_units_uses_exact_lookup_at_full_threshold( |
| 3434 | + self, adjust_threshold |
| 3435 | + ) -> None: |
| 3436 | + machine = WeblateTranslation({}) |
| 3437 | + base = MagicMock() |
| 3438 | + queryset = MagicMock() |
| 3439 | + ordered_queryset = MagicMock() |
| 3440 | + prepared_queryset = MagicMock() |
| 3441 | + exact_match = MagicMock(pk=1) |
| 3442 | + base.filter.return_value = queryset |
| 3443 | + queryset.order_by.return_value = ordered_queryset |
| 3444 | + prepared_queryset.iterator.return_value = [exact_match] |
| 3445 | + |
| 3446 | + with patch.object( |
| 3447 | + machine, "prepare_queryset", return_value=prepared_queryset |
| 3448 | + ) as prepare_queryset: |
| 3449 | + results = machine.get_matching_units(base, "Hello", 100) |
| 3450 | + |
| 3451 | + self.assertEqual(results, [exact_match]) |
| 3452 | + queryset.order_by.assert_called_once_with("pk") |
| 3453 | + prepare_queryset.assert_called_once_with(ordered_queryset) |
| 3454 | + prepared_queryset.iterator.assert_called_once_with( |
| 3455 | + chunk_size=machine.candidate_limit |
| 3456 | + ) |
| 3457 | + adjust_threshold.assert_not_called() |
| 3458 | + |
| 3459 | + def test_download_translations_limits_after_filtering(self) -> None: |
| 3460 | + machine = WeblateTranslation({}) |
| 3461 | + machine.candidate_limit = 2 |
| 3462 | + machine.comparer = MagicMock() |
| 3463 | + machine.comparer.similarity.side_effect = [95, 90, 85] |
| 3464 | + |
| 3465 | + filtered_match = MagicMock() |
| 3466 | + filtered_match.source_string = "ignored" |
| 3467 | + filtered_match.all_flags = {"forbidden"} |
| 3468 | + |
| 3469 | + first_match = MagicMock() |
| 3470 | + first_match.source_string = "first" |
| 3471 | + first_match.all_flags = set() |
| 3472 | + first_match.get_target_plurals.return_value = ["First"] |
| 3473 | + first_match.translation.component = "Component" |
| 3474 | + first_match.get_absolute_url.return_value = "/first/" |
| 3475 | + |
| 3476 | + second_match = MagicMock() |
| 3477 | + second_match.source_string = "second" |
| 3478 | + second_match.all_flags = set() |
| 3479 | + second_match.get_target_plurals.return_value = ["Second"] |
| 3480 | + second_match.translation.component = "Component" |
| 3481 | + second_match.get_absolute_url.return_value = "/second/" |
| 3482 | + |
| 3483 | + third_match = MagicMock() |
| 3484 | + third_match.source_string = "third" |
| 3485 | + third_match.all_flags = set() |
| 3486 | + third_match.get_target_plurals.return_value = ["Third"] |
| 3487 | + third_match.translation.component = "Component" |
| 3488 | + third_match.get_absolute_url.return_value = "/third/" |
| 3489 | + |
| 3490 | + with ( |
| 3491 | + patch.object(machine, "get_base_queryset", return_value=MagicMock()), |
| 3492 | + patch.object( |
| 3493 | + machine, |
| 3494 | + "get_matching_units", |
| 3495 | + return_value=[filtered_match, first_match, second_match, third_match], |
| 3496 | + ), |
| 3497 | + ): |
| 3498 | + results = list( |
| 3499 | + machine.download_translations( |
| 3500 | + "en", |
| 3501 | + "cs", |
| 3502 | + "Hello", |
| 3503 | + unit=None, |
| 3504 | + user=None, |
| 3505 | + threshold=10, |
| 3506 | + ) |
| 3507 | + ) |
| 3508 | + |
| 3509 | + self.assertEqual([item["text"] for item in results], ["First", "Second"]) |
| 3510 | + self.assertEqual(machine.comparer.similarity.call_count, 2) |
| 3511 | + |
| 3512 | + |
3321 | 3513 | class CommandTest(FixtureTestCase): |
3322 | 3514 | """Test for management commands.""" |
3323 | 3515 |
|
|
0 commit comments