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(); } /** * The extensibility guarantee, asserted against the enum rather than against a fixed list: * a new ResourceType case must produce a working tile without anyone editing a template. */ public function testThereIsATileForEveryBookableKind(): void { $this->client->loginUser($this->user()); $crawler = $this->client->request('GET', '/'); self::assertResponseIsSuccessful(); foreach (ResourceType::cases() as $type) { self::assertCount( 1, $crawler->filter(\sprintf('a[href="/book/%s"]', $type->value)), \sprintf('no dashboard tile links to the %s board', $type->value), ); self::assertStringContainsString($type->plural(), $crawler->html()); } } /** * The bookings list is only reachable from here now that the sidebar is gone. */ public function testTheDashboardLinksToTheBookingsList(): void { $this->client->loginUser($this->user()); $crawler = $this->client->request('GET', '/'); self::assertCount(1, $crawler->filter('a[href="/bookings"]')); } public function testTheNavigationIsGone(): void { $this->client->loginUser($this->user()); $crawler = $this->client->request('GET', '/'); self::assertCount(0, $crawler->filter('#mobilenav')); self::assertCount(1, $crawler->filter('a[href="/logout"]')); } public function testATileCountsWhatIsStillFreeToday(): void { $user = $this->user(); $today = new \DateTimeImmutable('today'); $this->resource('D1'); $taken = $this->resource('D2'); $this->em->persist(new Booking($this->user('bea@ep-reisen.de'), $taken, $today)); $this->em->flush(); $this->client->loginUser($user); $crawler = $this->client->request('GET', '/'); $tile = $crawler->filter('a[href="/book/desk"]')->text(); self::assertStringContainsString('von 2 heute frei', $tile); self::assertStringContainsString('1', $tile); } /** * A part-day booking still makes the resource "not free today" -- the dashboard has no span * to qualify the answer with, so it takes the whole day. */ public function testAPartDayBookingCountsAsTakenForTheDay(): void { $desk = $this->resource('D1'); $this->em->persist(new Booking($this->user('bea@ep-reisen.de'), $desk, new \DateTimeImmutable('today'), TimeRange::fromMinutes(540, 780))); $this->em->flush(); $this->client->loginUser($this->user()); $crawler = $this->client->request('GET', '/'); self::assertStringContainsString('heute alles belegt', $crawler->filter('a[href="/book/desk"]')->text()); } public function testYourOwnBookingIsCalledOutOnTheTile(): void { $user = $this->user(); $this->em->persist(new Booking($user, $this->resource('D1'), new \DateTimeImmutable('today'))); $this->em->flush(); $this->client->loginUser($user); $crawler = $this->client->request('GET', '/'); self::assertStringContainsString('D1', $crawler->filter('a[href="/book/desk"]')->text()); } public function testABoardOnlyShowsItsOwnKindOfResource(): void { $this->resource('D1'); $this->resource('P1', ResourceType::PARKING); $this->client->loginUser($this->user()); $desks = $this->client->request('GET', '/book/desk')->html(); self::assertStringContainsString('D1', $desks); self::assertStringNotContainsString('P1', $desks); $parking = $this->client->request('GET', '/book/parking')->html(); self::assertStringContainsString('P1', $parking); self::assertStringNotContainsString('D1', $parking); } public function testAnUnknownBookingAreaIsNotFound(): void { $this->client->loginUser($this->user()); $this->client->request('GET', '/book/bikes'); self::assertResponseStatusCodeSame(404); } public function testABoardWithNothingSetUpSaysSo(): void { $this->client->loginUser($this->user()); self::assertStringContainsString( 'noch nichts eingerichtet', $this->client->request('GET', '/book/parking')->html(), ); } private function user(string $email = 'anna@ep-reisen.de'): User { $user = new User($email, 'Test'); $user->setRoles(['ROLE_EMPLOYEE']); $this->em->persist($user); $this->em->flush(); return $user; } private function resource(string $label, ResourceType $type = ResourceType::DESK): Resource { $resource = new Resource($type, $label); $this->em->persist($resource); $this->em->flush(); return $resource; } }