feat: real API-driven search pagination
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests unitaires pour searchVideos() (includes/config.php).
|
||||
*
|
||||
* Aucun appel réseau : des réponses API factices sont pré-déposées dans le
|
||||
* cache (callPeerTubeApiCached consulte le cache avant tout appel cURL, qui
|
||||
* de toute façon échouerait avec PEERTUBE_URL = http://127.0.0.1). Le
|
||||
* répertoire de cache de l'instance globale est redirigé vers un dossier
|
||||
* temporaire via réflexion pour ne jamais toucher au cache réel (cache/api).
|
||||
*/
|
||||
|
||||
$cache = $GLOBALS['simple_api_cache'];
|
||||
$cacheDirProperty = new ReflectionProperty(SimpleAPICache::class, 'cacheDir');
|
||||
$cacheDirProperty->setAccessible(true);
|
||||
|
||||
$tmpDir = sys_get_temp_dir() . '/annu-kute-search-test-' . getmypid();
|
||||
if (!is_dir($tmpDir)) {
|
||||
mkdir($tmpDir, 0755, true);
|
||||
}
|
||||
$cacheDirProperty->setValue($cache, $tmpDir);
|
||||
|
||||
/**
|
||||
* Fabrique une entrée vidéo brute minimale au format API PeerTube
|
||||
*/
|
||||
function fakeApiVideo($uuid, $name = 'Vidéo de test') {
|
||||
return [
|
||||
'uuid' => $uuid,
|
||||
'name' => $name,
|
||||
'duration' => 42,
|
||||
'publishedAt' => '2024-01-01T00:00:00.000Z'
|
||||
];
|
||||
}
|
||||
|
||||
// --- Requête vide -----------------------------------------------------------
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('', 12, 0, $total);
|
||||
assertEquals([], $videos, 'une requête vide retourne un tableau vide');
|
||||
assertEquals(0, $total, 'une requête vide donne un total de 0');
|
||||
|
||||
// --- Paramètres de la requête API (identiques à ceux de searchVideos) -------
|
||||
|
||||
$paramsPage1 = [
|
||||
'search' => 'assemblee',
|
||||
'count' => 12,
|
||||
'start' => 0,
|
||||
'isLocal' => true,
|
||||
'sort' => '-publishedAt'
|
||||
];
|
||||
$paramsPage2 = $paramsPage1;
|
||||
$paramsPage2['start'] = 12;
|
||||
|
||||
// Deux pages factices : total 25, 12 vidéos en page 1, 13 en page 2
|
||||
$dataPage1 = [];
|
||||
for ($i = 1; $i <= 12; $i++) {
|
||||
$dataPage1[] = fakeApiVideo('uuid-page1-' . $i);
|
||||
}
|
||||
$dataPage2 = [];
|
||||
for ($i = 1; $i <= 13; $i++) {
|
||||
$dataPage2[] = fakeApiVideo('uuid-page2-' . $i);
|
||||
}
|
||||
$cache->set('search/videos', $paramsPage1, ['total' => 25, 'data' => $dataPage1]);
|
||||
$cache->set('search/videos', $paramsPage2, ['total' => 25, 'data' => $dataPage2]);
|
||||
|
||||
// --- Total réel renvoyé par l'API -------------------------------------------
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('assemblee', 12, 0, $total);
|
||||
assertEquals(12, count($videos), 'la page 1 retourne les 12 vidéos de la réponse');
|
||||
assertEquals(25, $total, 'le total provient de l\'API (25), pas du nombre de vidéos reçues');
|
||||
assertEquals('uuid-page1-1', $videos[0]['id'], 'les vidéos sont formatées par formatVideosData');
|
||||
|
||||
// --- Le paramètre start pilote la pagination ---------------------------------
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('assemblee', 12, 12, $total);
|
||||
assertEquals(13, count($videos), 'start=12 retourne la deuxième page (13 vidéos)');
|
||||
assertEquals('uuid-page2-1', $videos[0]['id'], 'start=12 interroge bien l\'API avec un décalage');
|
||||
assertEquals(25, $total, 'le total reste le même sur la deuxième page');
|
||||
|
||||
// --- Recherche par hashtag (endpoint videos) ---------------------------------
|
||||
|
||||
$paramsTag = [
|
||||
'tagsOneOf' => 'reunion',
|
||||
'count' => 12,
|
||||
'start' => 0,
|
||||
'isLocal' => true,
|
||||
'sort' => '-publishedAt'
|
||||
];
|
||||
$cache->set('videos', $paramsTag, ['total' => 3, 'data' => [
|
||||
fakeApiVideo('uuid-tag-1'),
|
||||
fakeApiVideo('uuid-tag-2'),
|
||||
fakeApiVideo('uuid-tag-3')
|
||||
]]);
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('#reunion', 12, 0, $total);
|
||||
assertEquals(3, count($videos), 'la recherche par hashtag retourne les vidéos du tag');
|
||||
assertEquals(3, $total, 'la recherche par hashtag renseigne aussi le total');
|
||||
|
||||
// --- Réponse sans clé total : repli sur le nombre de vidéos reçues ----------
|
||||
|
||||
$paramsSansTotal = $paramsPage1;
|
||||
$paramsSansTotal['search'] = 'sanstotal';
|
||||
$cache->set('search/videos', $paramsSansTotal, ['data' => [
|
||||
fakeApiVideo('uuid-st-1'),
|
||||
fakeApiVideo('uuid-st-2')
|
||||
]]);
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('sanstotal', 12, 0, $total);
|
||||
assertEquals(2, count($videos), 'réponse sans total : les vidéos sont retournées');
|
||||
assertEquals(2, $total, 'réponse sans total : repli sur le nombre de vidéos reçues');
|
||||
|
||||
// --- Aucune entrée en cache et réseau bloqué : résultat vide -----------------
|
||||
|
||||
$total = null;
|
||||
$videos = searchVideos('jamaisencache', 12, 0, $total);
|
||||
assertEquals([], $videos, 'sans cache ni réseau, la recherche retourne un tableau vide');
|
||||
assertEquals(0, $total, 'sans cache ni réseau, le total vaut 0');
|
||||
|
||||
// --- Nettoyage du dossier temporaire ----------------------------------------
|
||||
|
||||
foreach (glob($tmpDir . '/cache_*.json') as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
rmdir($tmpDir);
|
||||
Reference in New Issue
Block a user