diff --git a/pontoon/contributors/tests/test_views.py b/pontoon/contributors/tests/test_views.py index fb77aa3bb3..f8d0fe709f 100644 --- a/pontoon/contributors/tests/test_views.py +++ b/pontoon/contributors/tests/test_views.py @@ -235,21 +235,26 @@ def test_default_period( @pytest.mark.django_db -def test_invalid_period( - member, mock_contributors_render, mock_users_translations_counts -): +def test_invalid_period(member, mock_users_translations_counts): """ Checks how view handles invalid period, it result in period being None - displays all data. """ # If period parameter is invalid value - member.client.get("/contributors/?period=invalidperiod") - assert mock_contributors_render.call_args[0][0]["period"] is None - assert mock_users_translations_counts.call_args[0][0] is None + with patch.object( + views.ContributorsView, "render_to_response", return_value=HttpResponse("") + ) as mock_contributors_render: + member.client.get("/contributors/?period=invalidperiod") + assert mock_contributors_render.call_args[0][0]["period"] is None + assert mock_users_translations_counts.call_args[0][0] is None # Period shouldn't be negative integer - member.client.get("/contributors/?period=-6") - assert mock_contributors_render.call_args[0][0]["period"] is None - assert mock_users_translations_counts.call_args[0][0] is None + # The ContributorsView URL is cached, so we need a new mock + with patch.object( + views.ContributorsView, "render_to_response", return_value=HttpResponse("") + ) as mock_contributors_render: + member.client.get("/contributors/?period=-6") + assert mock_contributors_render.call_args[0][0]["period"] is None + assert mock_users_translations_counts.call_args[0][0] is None @pytest.mark.django_db diff --git a/pontoon/contributors/urls.py b/pontoon/contributors/urls.py index f772f46985..65f2d9bc6e 100644 --- a/pontoon/contributors/urls.py +++ b/pontoon/contributors/urls.py @@ -1,7 +1,10 @@ from django.urls import path, register_converter from django.urls.converters import StringConverter +from django.views.decorators.cache import cache_page from django.views.generic import RedirectView +from pontoon.settings import VIEW_CACHE_TIMEOUT + from . import views @@ -25,7 +28,7 @@ class UsernameConverter(StringConverter): # List contributors path( "contributors/", - views.ContributorsView.as_view(), + cache_page(VIEW_CACHE_TIMEOUT)(views.ContributorsView.as_view()), name="pontoon.contributors", ), # Contributor profile by username diff --git a/pontoon/localizations/urls.py b/pontoon/localizations/urls.py index 6dfc767899..a211c69085 100644 --- a/pontoon/localizations/urls.py +++ b/pontoon/localizations/urls.py @@ -1,6 +1,8 @@ from django.urls import include, path, re_path +from django.views.decorators.cache import cache_page from pontoon.projects import views as projects_views +from pontoon.settings import VIEW_CACHE_TIMEOUT from pontoon.teams import views as teams_views from . import views @@ -66,7 +68,9 @@ # Localization contributors path( "contributors/", - views.LocalizationContributorsView.as_view(), + cache_page(VIEW_CACHE_TIMEOUT)( + views.LocalizationContributorsView.as_view() + ), name="pontoon.localizations.ajax.contributors", ), # Project insights diff --git a/pontoon/projects/tests/test_views.py b/pontoon/projects/tests/test_views.py index 4225b08656..e5349acea9 100644 --- a/pontoon/projects/tests/test_views.py +++ b/pontoon/projects/tests/test_views.py @@ -78,6 +78,11 @@ def test_project_top_contributors(client, project_a, project_b): project_a_contributor ] + # The ProjectContributorsView URL is cached, so we need a new mock + with patch( + "pontoon.projects.views.ProjectContributorsView.render_to_response", + return_value=HttpResponse(""), + ) as mock_render: client.get( f"/projects/{project_b.slug}/ajax/contributors/", HTTP_X_REQUESTED_WITH="XMLHttpRequest", diff --git a/pontoon/projects/urls.py b/pontoon/projects/urls.py index bc64cbd122..35ad9a4635 100644 --- a/pontoon/projects/urls.py +++ b/pontoon/projects/urls.py @@ -1,6 +1,9 @@ from django.urls import include, path +from django.views.decorators.cache import cache_page from django.views.generic import RedirectView +from pontoon.settings import VIEW_CACHE_TIMEOUT + from . import views urlpatterns = [ @@ -70,7 +73,9 @@ # Project contributors path( "contributors/", - views.ProjectContributorsView.as_view(), + cache_page(VIEW_CACHE_TIMEOUT)( + views.ProjectContributorsView.as_view() + ), name="pontoon.projects.ajax.contributors", ), # Project insights diff --git a/pontoon/settings/base.py b/pontoon/settings/base.py index 1f45038f7a..b494bda8c6 100644 --- a/pontoon/settings/base.py +++ b/pontoon/settings/base.py @@ -674,6 +674,9 @@ def _default_from_email(): } } +# Default timeout for the per-view cache, in seconds. +VIEW_CACHE_TIMEOUT = 60 * 60 * 24 # 1 day + # Site ID is used by Django's Sites framework. SITE_ID = 1 diff --git a/pontoon/teams/tests/test_views.py b/pontoon/teams/tests/test_views.py index 9f9e17fb03..ddde18f1e7 100644 --- a/pontoon/teams/tests/test_views.py +++ b/pontoon/teams/tests/test_views.py @@ -170,28 +170,29 @@ def test_users_permissions_for_ajax_permissions_view( @pytest.mark.django_db -@patch( - "pontoon.teams.views.LocaleContributorsView.render_to_response", - return_value=HttpResponse(""), -) -def test_locale_top_contributors(mock_render, client, translation_a, locale_b): +def test_locale_top_contributors(client, translation_a, locale_b): """ Tests if the view returns top contributors specific for given locale. """ - client.get( - f"/{translation_a.locale.code}/ajax/contributors/", - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - - response_context = mock_render.call_args[0][0] - assert response_context["locale"] == translation_a.locale - assert list(response_context["contributors"]) == [translation_a.user] - - client.get( - f"/{locale_b.code}/ajax/contributors/", - HTTP_X_REQUESTED_WITH="XMLHttpRequest", - ) - - response_context = mock_render.call_args[0][0] - assert response_context["locale"] == locale_b - assert list(response_context["contributors"]) == [] + with patch( + "pontoon.teams.views.LocaleContributorsView.render_to_response", + return_value=HttpResponse(""), + ) as mock_render: + client.get( + f"/{translation_a.locale.code}/ajax/contributors/", + HTTP_X_REQUESTED_WITH="XMLHttpRequest", + ) + assert mock_render.call_args[0][0]["locale"] == translation_a.locale + assert list(mock_render.call_args[0][0]["contributors"]) == [translation_a.user] + + # The LocaleContributorsView URL is cached, so we need a new mock + with patch( + "pontoon.teams.views.LocaleContributorsView.render_to_response", + return_value=HttpResponse(""), + ) as mock_render: + client.get( + f"/{locale_b.code}/ajax/contributors/", + HTTP_X_REQUESTED_WITH="XMLHttpRequest", + ) + assert mock_render.call_args[0][0]["locale"] == locale_b + assert list(mock_render.call_args[0][0]["contributors"]) == [] diff --git a/pontoon/teams/urls.py b/pontoon/teams/urls.py index 03959b0c18..cb3fc0f6ba 100644 --- a/pontoon/teams/urls.py +++ b/pontoon/teams/urls.py @@ -1,6 +1,9 @@ from django.urls import include, path +from django.views.decorators.cache import cache_page from django.views.generic import RedirectView +from pontoon.settings import VIEW_CACHE_TIMEOUT + from . import views @@ -70,7 +73,9 @@ # Team contributors path( "contributors/", - views.LocaleContributorsView.as_view(), + cache_page(VIEW_CACHE_TIMEOUT)( + views.LocaleContributorsView.as_view() + ), name="pontoon.teams.ajax.contributors", ), # Team insights