diff --git a/tests/Module/Catalog/Api/CategoryPaginationTest.php b/tests/Module/Catalog/Api/CategoryPaginationTest.php new file mode 100644 index 0000000..b0e418b --- /dev/null +++ b/tests/Module/Catalog/Api/CategoryPaginationTest.php @@ -0,0 +1,171 @@ +createCategoryType(); + for ($i = 1; $i <= 12; ++$i) { + $this->createCategory(self::TEST_CATEGORY_PREFIX.'meta_'.$i, $type); + } + + $client = $this->createAdminClient(); + $response = $client->request('GET', '/api/categories'); + + self::assertSame(200, $response->getStatusCode()); + + $data = $response->toArray(); + self::assertArrayHasKey('totalItems', $data, 'La collection doit exposer totalItems.'); + self::assertArrayHasKey('view', $data, 'La collection doit exposer view (pagination) quand totalItems > itemsPerPage.'); + self::assertIsArray($data['member'], 'member doit etre un tableau.'); + } + + /** + * Un itemsPerPage arbitrairement grand (99999) doit etre plafonne au + * maximum global configure (50). On cree 12 categories pour etre certain + * de disposer de donnees ; le cap doit s'appliquer quelle que soit la taille + * reelle de la collection. + */ + public function testItemsPerPageIsCappedAtMaximum(): void + { + $type = $this->createCategoryType(); + for ($i = 1; $i <= 12; ++$i) { + $this->createCategory(self::TEST_CATEGORY_PREFIX.'cap_'.$i, $type); + } + + $client = $this->createAdminClient(); + $response = $client->request('GET', '/api/categories?itemsPerPage=99999'); + + self::assertSame(200, $response->getStatusCode()); + // Le cap global est 50 : jamais plus d'items par page que le maximum. + self::assertLessThanOrEqual( + 50, + count($response->toArray()['member']), + 'itemsPerPage doit etre plafonne au maximum global (50).', + ); + } + + /** + * Une page tres elevee (99999) sur une petite collection ne doit pas + * produire une 500 PG (OFFSET negatif ou depassement de capacite) mais + * retourner 200 avec un tableau member vide. + */ + public function testOutOfBoundPageReturnsEmptyCollectionNot500(): void + { + $type = $this->createCategoryType(); + $this->createCategory(self::TEST_CATEGORY_PREFIX.'oob', $type); + + $client = $this->createAdminClient(); + $response = $client->request('GET', '/api/categories?page=99999'); + + self::assertSame(200, $response->getStatusCode()); + // La page 99999 est forcement vide (on a bien moins que 99999*10 items). + self::assertSame( + [], + $response->toArray()['member'], + 'Une page hors limites doit retourner un member vide, jamais une 500.', + ); + } + + /** + * ?pagination=false permet au frontend de desactiver la pagination pour + * alimenter un select-box. On cree exactement 12 categories dont les noms + * commencent par `test_cat_select_` : le filtre sur ce prefixe isole nos + * entrees des donnees concurrentes et prouve que les 12 items sont tous + * retournes (et pas seulement les 10 premiers de la page 1). + */ + public function testClientCanDisablePaginationToFeedASelect(): void + { + $type = $this->createCategoryType(); + for ($i = 1; $i <= 12; ++$i) { + $this->createCategory(self::TEST_CATEGORY_PREFIX.'select_'.$i, $type); + } + + $client = $this->createAdminClient(); + $response = $client->request('GET', '/api/categories?pagination=false'); + + self::assertSame(200, $response->getStatusCode()); + + $members = $response->toArray()['member']; + + // Filtre sur le sous-prefixe pour ne pas comptabiliser les categories + // d'autres tests qui partagent la meme base de donnees. + $selectItems = array_values(array_filter( + $members, + fn (array $m): bool => str_starts_with($m['name'], self::TEST_CATEGORY_PREFIX.'select_'), + )); + + self::assertCount( + 12, + $selectItems, + '?pagination=false doit retourner toutes les categories (pas seulement la page 1).', + ); + } + + /** + * La pagination doit fonctionner conjointement avec le flag ?includeDeleted=true. + * On seed 3 categories actives + 2 soft-deleted, on demande itemsPerPage=5 : + * la page 1 doit contenir exactement 5 items et totalItems doit valoir >= 5. + */ + public function testPaginationCombinedWithIncludeDeletedFlag(): void + { + $type = $this->createCategoryType(); + + // 3 categories actives. + for ($i = 1; $i <= 3; ++$i) { + $this->createCategory(self::TEST_CATEGORY_PREFIX.'pag_active_'.$i, $type); + } + + // 2 categories soft-deleted. + for ($i = 1; $i <= 2; ++$i) { + $this->createCategory( + self::TEST_CATEGORY_PREFIX.'pag_deleted_'.$i, + $type, + new DateTimeImmutable(), + ); + } + + $client = $this->createAdminClient(); + $response = $client->request('GET', '/api/categories?includeDeleted=true&itemsPerPage=5'); + + self::assertSame(200, $response->getStatusCode()); + + $data = $response->toArray(); + // La page retournee ne doit pas exceder itemsPerPage=5. + self::assertCount( + 5, + $data['member'], + 'La page 1 doit contenir exactement 5 items (itemsPerPage=5 avec >= 5 categories disponibles).', + ); + self::assertGreaterThanOrEqual( + 5, + $data['totalItems'], + 'totalItems doit refleter au moins les 5 categories seedees (actives + soft-deleted).', + ); + } +} diff --git a/tests/Module/Core/Api/AuditLogPaginationRegressionTest.php b/tests/Module/Core/Api/AuditLogPaginationRegressionTest.php new file mode 100644 index 0000000..9e29da6 --- /dev/null +++ b/tests/Module/Core/Api/AuditLogPaginationRegressionTest.php @@ -0,0 +1,71 @@ +authenticatedClient('admin', 'admin'); + $response = $client->request('GET', '/api/audit-logs'); + + self::assertSame(200, $response->getStatusCode()); + + $data = $response->toArray(); + self::assertArrayHasKey('totalItems', $data, 'La collection audit-logs doit exposer totalItems.'); + self::assertArrayHasKey('view', $data, 'La collection audit-logs doit exposer view (pagination active).'); + self::assertIsArray($data['member'], 'member doit etre un tableau.'); + + // Le nouveau defaut global est 10 (etait 30 dans AuditLogResource avant ERP-72). + self::assertLessThanOrEqual( + 10, + count($data['member']), + 'La page par defaut ne doit pas depasser 10 items (default global ERP-72).', + ); + } + + /** + * Un itemsPerPage excessif (99999) doit etre plafonne au maximum global (50). + * Teste la regression specifique du paginator DBAL custom (DbalPaginator) qui + * pourrait ignorer la limite si la logique de cap n'est pas appliquee cote provider. + */ + public function testAuditLogItemsPerPageCappedAt50(): void + { + $client = $this->authenticatedClient('admin', 'admin'); + $response = $client->request('GET', '/api/audit-logs?itemsPerPage=99999'); + + self::assertSame(200, $response->getStatusCode()); + + $data = $response->toArray(); + self::assertIsArray($data['member'], 'member doit etre un tableau.'); + + // Le cap global est 50 : jamais plus d'items par page que le maximum. + self::assertLessThanOrEqual( + 50, + count($data['member']), + 'itemsPerPage=99999 doit etre plafonne a 50 (maximum global ERP-72).', + ); + } +}