client = self::createClient(server: ['HTTPS' => true]); $this->client->disableReboot(); $this->em = self::getContainer()->get(EntityManagerInterface::class); $this->em->getConnection()->beginTransaction(); } protected function tearDown(): void { $this->em->getConnection()->rollBack(); parent::tearDown(); } public function testItIsBehindTheFirewall(): void { $this->client->request('GET', '/access-codes'); self::assertResponseRedirects(); } public function testAnEmployeeSeesACardPerDoor(): void { $this->code('Aufzug', '4711', description: 'Kabine im Erdgeschoss'); $this->code('Schranke', '1234'); $this->em->flush(); $this->client->loginUser($this->user('anna@ep-reisen.de')); $cards = $this->client->request('GET', '/access-codes')->filter('[data-access-code]'); self::assertResponseIsSuccessful(); self::assertCount(2, $cards); self::assertStringContainsString('Aufzug', $cards->eq(0)->text()); self::assertStringContainsString('Kabine im Erdgeschoss', $cards->eq(0)->text()); self::assertSame('4711', $cards->eq(0)->filter('[data-code]')->text()); self::assertSame('1234', $cards->eq(1)->filter('[data-code]')->text()); } /** * The restriction is a filter on the query, not a hidden card: a code an employee may not * read must not be in the response at all. */ public function testAnAdminOnlyCodeIsNotSentToAnEmployee(): void { $this->code('Serverraum', '9999', visibility: CodeVisibility::ADMIN); $this->em->flush(); $this->client->loginUser($this->user('anna@ep-reisen.de')); $crawler = $this->client->request('GET', '/access-codes'); self::assertCount(0, $crawler->filter('[data-access-code]')); self::assertStringNotContainsString('9999', (string) $this->client->getResponse()->getContent()); $this->client->loginUser($this->user('chef@ep-reisen.de', ['ROLE_ADMIN'])); $card = $this->client->request('GET', '/access-codes')->filter('[data-access-code]'); self::assertCount(1, $card); self::assertSame('9999', $card->filter('[data-code]')->text()); self::assertStringContainsString('Administration', $card->text()); } /** * Rotating a code. Only the one in force is shown: its predecessor is history, and its * successor does not open anything yet -- both would only be another number to mistype. */ public function testOnlyTheCodeInForceIsShown(): void { $this->code('Aufzug', 'OLD', validFrom: '-2 months'); $this->code('Aufzug', 'NOW', validFrom: '-1 day'); $this->code('Aufzug', 'NEXT', validFrom: '+1 month'); $this->em->flush(); $this->client->loginUser($this->user('anna@ep-reisen.de')); $cards = $this->client->request('GET', '/access-codes')->filter('[data-access-code]'); self::assertCount(1, $cards); self::assertSame('NOW', $cards->filter('[data-code]')->text()); $body = (string) $this->client->getResponse()->getContent(); self::assertStringNotContainsString('OLD', $body); self::assertStringNotContainsString('NEXT', $body); } /** * A code that starts on a date starts that morning, not the day after. */ public function testACodeStartingTodayIsInForce(): void { $this->code('Aufzug', '4711', validFrom: 'today'); $this->em->flush(); $this->client->loginUser($this->user('anna@ep-reisen.de')); $cards = $this->client->request('GET', '/access-codes')->filter('[data-access-code]'); self::assertCount(1, $cards); self::assertSame('4711', $cards->filter('[data-code]')->text()); } /** * A door that only has a code for next week is simply not on the page yet. */ public function testADoorWithNoCodeInForceIsAbsent(): void { $this->code('Schranke', 'SOON', validFrom: '+1 week'); $this->em->flush(); $this->client->loginUser($this->user('anna@ep-reisen.de')); $crawler = $this->client->request('GET', '/access-codes'); self::assertCount(0, $crawler->filter('[data-access-code]')); self::assertStringContainsString('Zurzeit gilt kein Code', $crawler->filter('body')->text()); } public function testOnlyAnAdminIsOfferedTheTable(): void { $this->client->loginUser($this->user('anna@ep-reisen.de')); self::assertCount(0, $this->client->request('GET', '/access-codes')->filter('a[href="/admin/access-codes"]')); $this->client->loginUser($this->user('chef@ep-reisen.de', ['ROLE_ADMIN'])); self::assertCount(1, $this->client->request('GET', '/access-codes')->filter('a[href="/admin/access-codes"]')); } public function testTheDashboardLinksHereForEveryone(): void { $this->client->loginUser($this->user('anna@ep-reisen.de')); self::assertCount(1, $this->client->request('GET', '/')->filter('a[href="/access-codes"]')); } private function code( string $label, string $value, string $validFrom = 'today', ?string $description = null, CodeVisibility $visibility = CodeVisibility::EVERYONE, ): AccessCode { $code = new AccessCode($label, $value, new \DateTimeImmutable($validFrom), $description, $visibility); $this->em->persist($code); return $code; } /** * @param list $roles */ private function user(string $email, array $roles = ['ROLE_EMPLOYEE']): User { $existing = $this->em->getRepository(User::class)->findOneBy(['email' => $email]); if (null !== $existing) { return $existing; } $user = new User($email, 'Test'); $user->setRoles($roles); $this->em->persist($user); $this->em->flush(); return $user; } }