request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01'); self::assertResponseStatusCodeSame(401); } public function testAdminCanListTimePerProject(): void { $client = self::createClient(); $this->loginUser($client, 'admin'); $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01'); self::assertResponseIsSuccessful(); $data = json_decode($client->getResponse()->getContent(), true); self::assertArrayHasKey('member', $data); // Le rapport est non pagine : la structure hydra expose tout de meme un // tableau `member`. Si des projets ont du temps logge, chaque membre // porte au minimum projectId et hours. foreach ($data['member'] as $row) { self::assertArrayHasKey('projectId', $row); self::assertArrayHasKey('hours', $row); self::assertIsInt($row['projectId']); } } public function testValidProjectIdFilterIsAccepted(): void { $client = self::createClient(); $this->loginUser($client, 'admin'); // projectId arrive en chaine ("1") : la validation doit l'accepter (200), // garde-fou contre une regression de type-juggling sur le filtre entier. $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01&projectId=1'); self::assertResponseIsSuccessful(); } public function testInvalidProjectIdFilterIsRejected(): void { $client = self::createClient(); $this->loginUser($client, 'admin'); $client->request('GET', '/api/reports/time-per-project?projectId=abc'); self::assertResponseStatusCodeSame(400); } public function testInvalidDateFilterIsRejected(): void { $client = self::createClient(); $this->loginUser($client, 'admin'); $client->request('GET', '/api/reports/time-per-project?from=not-a-date'); self::assertResponseStatusCodeSame(400); } public function testUserWithoutPermissionIsForbidden(): void { $client = self::createClient(); $this->loginUser($client, 'alice'); $client->request('GET', '/api/reports/time-per-project?from=2026-01-01&to=2027-01-01'); self::assertResponseStatusCodeSame(403); } private function loginUser(KernelBrowser $client, string $username): void { $em = self::getContainer()->get(EntityManagerInterface::class); $user = $em->getRepository(User::class)->findOneBy(['username' => $username]); self::assertInstanceOf(User::class, $user); $client->loginUser($user); } }