diff --git a/swh/web/misc/origin_save.py b/swh/web/misc/origin_save.py --- a/swh/web/misc/origin_save.py +++ b/swh/web/misc/origin_save.py @@ -5,6 +5,7 @@ from django.conf.urls import url from django.core.paginator import Paginator +from django.db.models import Q from django.http import JsonResponse from django.shortcuts import render from rest_framework.decorators import api_view, authentication_classes @@ -75,20 +76,20 @@ length = int(request.GET["length"]) page = int(request.GET["start"]) / length + 1 - save_requests = get_save_origin_requests_from_queryset(save_requests) + if search_value: - save_requests = [ - sr - for sr in save_requests - if search_value.lower() in sr["save_request_status"].lower() - or search_value.lower() in sr["save_task_status"].lower() - or search_value.lower() in sr["visit_type"].lower() - or search_value.lower() in sr["origin_url"].lower() - ] - - table_data["recordsFiltered"] = len(save_requests) + save_requests = save_requests.filter( + Q(status__icontains=search_value) + | Q(loading_task_status__icontains=search_value) + | Q(visit_type__icontains=search_value) + | Q(origin_url__icontains=search_value) + ) + + table_data["recordsFiltered"] = save_requests.count() paginator = Paginator(save_requests, length) - table_data["data"] = paginator.page(page).object_list + table_data["data"] = get_save_origin_requests_from_queryset( + paginator.page(page).object_list + ) return JsonResponse(table_data) diff --git a/swh/web/tests/misc/test_origin_save.py b/swh/web/tests/misc/test_origin_save.py --- a/swh/web/tests/misc/test_origin_save.py +++ b/swh/web/tests/misc/test_origin_save.py @@ -3,15 +3,18 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -from datetime import datetime +from datetime import datetime, timedelta, timezone +import json import pytest from django.test import Client +from swh.web.common.models import SaveOriginRequest from swh.web.common.origin_save import ( SAVE_REQUEST_ACCEPTED, SAVE_TASK_NOT_YET_SCHEDULED, + SAVE_TASK_SUCCEEDED, ) from swh.web.common.utils import reverse from swh.web.settings.tests import save_origin_rate_post @@ -88,6 +91,80 @@ assert resp["location"] == redirect_url +@pytest.mark.django_db +def test_save_origin_requests_list(client, mocker): + visit_types = ("git", "svn", "hg") + nb_origins_per_type = 10 + for visit_type in visit_types: + for i in range(nb_origins_per_type): + SaveOriginRequest.objects.create( + request_date=datetime.now(tz=timezone.utc), + visit_type=visit_type, + origin_url=f"https://{visit_type}.example.org/project{i}", + status=SAVE_REQUEST_ACCEPTED, + visit_date=datetime.now(tz=timezone.utc) + timedelta(hours=1), + loading_task_id=i, + loading_task_status=SAVE_TASK_SUCCEEDED, + ) + + mock_scheduler = mocker.patch("swh.web.common.origin_save.scheduler") + mock_scheduler.get_tasks.return_value = [] + mock_scheduler.get_task_runs.return_value = [] + + # retrieve all save requests in 3 pages, sorted in descending order + # of request creation + for i, visit_type in enumerate(reversed(visit_types)): + url = reverse( + "origin-save-requests-list", + url_args={"status": "all"}, + query_params={ + "draw": i + 1, + "search[value]": "", + "order[0][column]": "0", + "columns[0][name]": "request_date", + "order[0][dir]": "desc", + "length": nb_origins_per_type, + "start": i * nb_origins_per_type, + }, + ) + + resp = check_http_get_response( + client, url, status_code=200, content_type="application/json" + ) + sors = json.loads(resp.content.decode("utf-8")) + assert sors["draw"] == i + 1 + assert sors["recordsFiltered"] == len(visit_types) * nb_origins_per_type + assert sors["recordsTotal"] == len(visit_types) * nb_origins_per_type + assert len(sors["data"]) == nb_origins_per_type + assert all(d["visit_type"] == visit_type for d in sors["data"]) + + # retrieve save requests filtered by visit type in a single page + for i, visit_type in enumerate(reversed(visit_types)): + url = reverse( + "origin-save-requests-list", + url_args={"status": "all"}, + query_params={ + "draw": i + 1, + "search[value]": visit_type, + "order[0][column]": "0", + "columns[0][name]": "request_date", + "order[0][dir]": "desc", + "length": nb_origins_per_type, + "start": 0, + }, + ) + + resp = check_http_get_response( + client, url, status_code=200, content_type="application/json" + ) + sors = json.loads(resp.content.decode("utf-8")) + assert sors["draw"] == i + 1 + assert sors["recordsFiltered"] == nb_origins_per_type + assert sors["recordsTotal"] == len(visit_types) * nb_origins_per_type + assert len(sors["data"]) == nb_origins_per_type + assert all(d["visit_type"] == visit_type for d in sors["data"]) + + def _get_csrf_token(client, url): resp = client.get(url) return {"csrfmiddlewaretoken": resp.cookies["csrftoken"].value}