"""Tests E2E de la pagination de la recherche (recherche.php). La pagination est déléguée à l'API PeerTube (paramètre start) et le total affiché est le total réel renvoyé par l'API — et non le nombre de vidéos réellement présentes sur la page. """ import json import math import re import urllib.parse import urllib.request import pytest VIDEOS_PAR_PAGE = 12 # VIDEOS_PER_PAGE (includes/config.default.php) TERMES_CANDIDATS = ["a", "e", "video", "les"] def _total_api(peertube_url, terme): """Total d'une recherche plein texte côté API PeerTube.""" params = urllib.parse.urlencode({ "search": terme, "isLocal": "true", "count": 1, }) url = f"{peertube_url}/api/v1/search/videos?{params}" with urllib.request.urlopen(url, timeout=30) as rep: return int(json.load(rep).get("total", 0)) def _nombre_resultats(page): """Extrait le total affiché dans le bandeau des résultats.""" texte = page.locator(".search-results-count p").inner_text() m = re.search(r"(\d+)", texte) assert m, f"Total introuvable dans le bandeau : {texte!r}" return int(m.group(1)) def _ids_cartes(page): """Identifiants des vidéos affichées dans la grille de résultats.""" cartes = page.locator(".video-grid .video-card") return { cartes.nth(i).get_attribute("data-video-id") for i in range(cartes.count()) } @pytest.fixture(scope="session") def terme_paginable(peertube_url): """Un terme de recherche couvrant au moins deux pages de résultats.""" for terme in TERMES_CANDIDATS: try: if _total_api(peertube_url, terme) > VIDEOS_PAR_PAGE: return terme except Exception: continue pytest.skip("Aucun terme avec plus d'une page de résultats (réseau ?)") def test_recherche_affiche_total_reel(page, base_url, peertube_url, terme_paginable): """Le total affiché est le total réel de l'API, pas le contenu de la page.""" total_api = _total_api(peertube_url, terme_paginable) page.goto( f"{base_url}/recherche.php?q={urllib.parse.quote(terme_paginable)}", wait_until="domcontentloaded", ) cartes = page.locator(".video-grid .video-card") if cartes.count() == 0: pytest.skip("Aucune vidéo reçue de l'API PeerTube (réseau indisponible ?)") total_affiche = _nombre_resultats(page) assert total_affiche == total_api # La première page ne contient qu'une page de résultats, pas le total assert total_affiche > cartes.count() assert cartes.count() == min(VIDEOS_PAR_PAGE, total_affiche) # La barre de pagination reflète le total réel assert page.locator(".pagination").count() == 1 assert page.locator(".page-number.current").inner_text() == "1" numeros = [ int(page.locator(".page-number").nth(i).inner_text()) for i in range(page.locator(".page-number").count()) ] assert max(numeros) == math.ceil(total_affiche / VIDEOS_PAR_PAGE) def test_recherche_navigation_page_2(page, base_url, terme_paginable): """Le lien « Suivant » mène à la page 2, avec des vidéos différentes.""" page.goto( f"{base_url}/recherche.php?q={urllib.parse.quote(terme_paginable)}", wait_until="domcontentloaded", ) ids_page1 = _ids_cartes(page) if not ids_page1: pytest.skip("Aucune vidéo reçue de l'API PeerTube (réseau indisponible ?)") page.locator(".page-link.next").click() page.wait_for_url(re.compile(r"[?&]page=2(&|$)")) assert page.locator(".page-number.current").inner_text() == "2" assert page.locator(".page-link.prev").count() == 1 ids_page2 = _ids_cartes(page) assert ids_page2, "La page 2 ne contient aucune vidéo" assert ids_page2.isdisjoint(ids_page1), "Les pages 1 et 2 partagent des vidéos" def test_recherche_page_hors_limites(page, base_url, terme_paginable): """Une page au-delà de la dernière retombe sur une page valide.""" page.goto( f"{base_url}/recherche.php?q={urllib.parse.quote(terme_paginable)}&page=99999999", wait_until="domcontentloaded", ) cartes = page.locator(".video-grid .video-card") if cartes.count() == 0: pytest.skip("Aucune vidéo reçue de l'API PeerTube (réseau indisponible ?)") # La page se rabat sur une page valide (jamais de grille vide ni d'erreur) total_affiche = _nombre_resultats(page) assert total_affiche > 0 assert page.locator(".page-number.current").count() == 1 page_courante = int(page.locator(".page-number.current").inner_text()) assert 1 <= page_courante <= math.ceil(total_affiche / VIDEOS_PAR_PAGE)