clearConfigCache(); parent::tearDown(); } protected function formatDateRange(\DateTime $begin, \DateTime $end): string { return $begin->format(self::DEFAULT_DATE_FORMAT) . DateRangeType::DATE_SPACER . $end->format(self::DEFAULT_DATE_FORMAT); } protected function formatDate(\DateTime $date): string { return $date->format(self::DEFAULT_DATE_FORMAT); } protected function formatDateTime(\DateTime $date): string { return $this->formatDate($date) . ' ' . $this->formatTime($date); } protected function formatTime(\DateTime $date): string { return $date->format(self::DEFAULT_TIME_FORMAT); } /** * Using a special container, to access private services as well. * * @param string $service * @return object|null * @see https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing */ protected function getPrivateService(string $service) { return self::getContainer()->get($service); } protected function loadUserFromDatabase(string $username): User { /** @var Registry $doctrine */ $doctrine = self::getContainer()->get('doctrine'); /** @var UserRepository $userRepository */ $userRepository = $doctrine->getRepository(User::class); $user = $userRepository->loadUserByIdentifier($username); self::assertInstanceOf(User::class, $user); return $user; } protected function setSystemConfiguration(string $name, $value): void { /** @var ConfigurationService $repository */ $repository = self::getContainer()->get(ConfigurationService::class); $entity = $repository->getConfiguration($name); if ($entity === null) { $entity = new Configuration(); $entity->setName($name); } $entity->setValue($value); $repository->saveConfiguration($entity); $this->clearConfigCache(); } protected function clearConfigCache(): void { /** @var ConfigurationService $service */ $service = self::getContainer()->get(ConfigurationService::class); $service->clearCache(); } protected function getClientForAuthenticatedUser(string $role = User::ROLE_USER): HttpKernelBrowser { $username = match ($role) { User::ROLE_SUPER_ADMIN => UserFixtures::USERNAME_SUPER_ADMIN, User::ROLE_ADMIN => UserFixtures::USERNAME_ADMIN, User::ROLE_TEAMLEAD => UserFixtures::USERNAME_TEAMLEAD, User::ROLE_USER => UserFixtures::USERNAME_USER, default => null, }; if ($username === null) { throw new \Exception('Unknown username: ' . $username); } return $this->loginByUsername($username); } protected function loginByUsername(string $username): HttpKernelBrowser { $client = static::createClient(); /** @var UserRepository $userRepository */ $userRepository = $this->getPrivateService(UserRepository::class); $user = $userRepository->findByUsername($username); if ($user === null) { throw new \Exception('Unknown user: ' . $username); } $client->loginUser($user, 'secured_area'); return $client; } protected function loginUser(User $user): HttpKernelBrowser { $client = static::createClient(); $client->loginUser($user, 'secured_area'); return $client; } /** * @return non-empty-string */ protected function createUrl(string $url): string { $prefix = '/' . self::DEFAULT_LANGUAGE; if (!str_starts_with($url, $prefix)) { $url = $prefix . '/' . ltrim($url, '/'); } return $url; } public function request(HttpKernelBrowser $client, string $url, string $method = 'GET', array $parameters = [], ?string $content = null): Crawler { return $client->request($method, $this->createUrl($url), $parameters, [], [], $content); } public function requestPure(HttpKernelBrowser $client, string $url, string $method = 'GET', array $parameters = [], ?string $content = null): Crawler { return $client->request($method, $url, $parameters, [], [], $content); } protected function assertRequestIsSecured(HttpKernelBrowser $client, string $url, string $method = 'GET'): void { $this->request($client, $url, $method); /** @var RedirectResponse $response */ $response = $client->getResponse(); self::assertTrue( $response->isRedirect(), \sprintf('The URL %s is not protected (%s occurred).', $url, $response->getStatusCode()) ); self::assertStringEndsWith( '/login', $response->getTargetUrl(), \sprintf('The URL %s does not redirect to the login form.', $url) ); self::assertInstanceOf(RedirectResponse::class, $response); } protected function assertSuccessResponse(HttpKernelBrowser $client, string $message = ''): void { $response = $client->getResponse(); self::assertThat($response, new ResponseConstraint\ResponseIsSuccessful(), 'Response is not successful, got code: ' . $response->getStatusCode()); } protected function assertUrlIsSecured(string $url, string $method = 'GET'): void { $client = self::createClient(); $this->assertRequestIsSecured($client, $url, $method); } protected function assertUrlIsSecuredForRole(string $role, string $url, string $method = 'GET'): void { $client = $this->getClientForAuthenticatedUser($role); $client->request($method, $this->createUrl($url)); self::assertFalse( $client->getResponse()->isSuccessful(), \sprintf('The secure URL %s is not protected for role %s', $url, $role) ); $this->assertAccessDenied($client); } protected function assertAccessDenied(HttpKernelBrowser $client): void { self::assertFalse( $client->getResponse()->isSuccessful(), 'Access is not denied for URL: ' . $client->getRequest()->getUri() ); self::assertStringContainsString( 'Page is restricted', $client->getResponse()->getContent(), 'Could not find AccessDeniedException in response' ); } protected function assertAccessIsGranted(HttpKernelBrowser $client, string $url, string $method = 'GET', array $parameters = []): void { $this->request($client, $url, $method, $parameters); self::assertTrue($client->getResponse()->isSuccessful()); } protected function assertRouteNotFound(HttpKernelBrowser $client): void { self::assertFalse($client->getResponse()->isSuccessful()); self::assertEquals(Response::HTTP_NOT_FOUND, $client->getResponse()->getStatusCode()); } protected function assertMainContentClass(HttpKernelBrowser $client, string $classname): void { self::assertStringContainsString('
', $client->getResponse()->getContent()); } protected function assertHasDataTable(HttpKernelBrowser $client): void { self::assertStringContainsString('getResponse()->headers->get('x-modal-redirect'); self::assertNotNull($location); // check for meta refresh $expectedMeta = \sprintf('', $location); self::assertStringContainsString($expectedMeta, $client->getResponse()->getContent()); if ($url !== null) { if ($endsWith && $url !== '') { self::assertStringEndsWith($url, $location, 'Redirect URL does not match'); } else { self::assertStringContainsString($url, $location, 'Redirect URL does not match'); } } return $location; } protected function assertRedirectUrl(HttpKernelBrowser $client, string $url, bool $endsWith = true): void { self::assertTrue($client->getResponse()->headers->has('Location'), 'Could not find "Location" header'); $location = $client->getResponse()->headers->get('Location'); self::assertNotNull($location); if ($endsWith && $url !== '') { self::assertStringEndsWith($url, $location, 'Redirect URL does not match'); } else { self::assertStringContainsString($url, $location, 'Redirect URL does not match'); } } protected function assertExcelExportResponse(HttpKernelBrowser $client, string $prefix): void { /** @var BinaryFileResponse $response */ $response = $client->getResponse(); self::assertInstanceOf(BinaryFileResponse::class, $response); $disposition = $response->headers->get('Content-Disposition'); self::assertNotNull($disposition); self::assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $response->headers->get('Content-Type')); self::assertStringContainsString('attachment; filename=' . $prefix, $disposition); self::assertStringContainsString('.xlsx', $disposition); } protected function assertInvalidCsrfToken(HttpKernelBrowser $client, string $url, string $expectedRedirect): void { $this->request($client, $url); $this->assertIsRedirect($client); $this->assertRedirectUrl($client, $expectedRedirect); $client->followRedirect(); $this->assertHasFlashError($client, 'The action could not be performed: invalid security token.'); } protected function getCsrfToken(HttpKernelBrowser $client, string $name): CsrfToken { $request = new Request(); $request->setSession(new Session(new MockArraySessionStorage())); /** @var RequestStack $stack */ $stack = self::getContainer()->get(RequestStack::class); $stack->push($request); /** @var CsrfTokenManager $tokenManager */ $tokenManager = self::getContainer()->get('security.csrf.token_manager'); return $tokenManager->getToken($name); } }