Files
kimai2/tests/API/APIControllerBaseTest.php
2019-09-19 20:28:31 +02:00

245 lines
8.0 KiB
PHP

<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\API;
use App\DataFixtures\UserFixtures;
use App\Entity\User;
use App\Tests\Controller\ControllerBaseTest;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\HttpFoundation\Response;
/**
* Adds some useful functions for writing API integration tests.
*/
abstract class APIControllerBaseTest extends ControllerBaseTest
{
protected function getClientForAuthenticatedUser(string $role = User::ROLE_USER): Client
{
switch ($role) {
case User::ROLE_SUPER_ADMIN:
$client = self::createClient([], [
'HTTP_X_AUTH_USER' => UserFixtures::USERNAME_SUPER_ADMIN,
'HTTP_X_AUTH_TOKEN' => UserFixtures::DEFAULT_API_TOKEN,
]);
break;
case User::ROLE_ADMIN:
$client = self::createClient([], [
'HTTP_X_AUTH_USER' => UserFixtures::USERNAME_ADMIN,
'HTTP_X_AUTH_TOKEN' => UserFixtures::DEFAULT_API_TOKEN,
]);
break;
case User::ROLE_TEAMLEAD:
$client = self::createClient([], [
'HTTP_X_AUTH_USER' => UserFixtures::USERNAME_TEAMLEAD,
'HTTP_X_AUTH_TOKEN' => UserFixtures::DEFAULT_API_TOKEN,
]);
break;
case User::ROLE_USER:
$client = self::createClient([], [
'HTTP_X_AUTH_USER' => UserFixtures::USERNAME_USER,
'HTTP_X_AUTH_TOKEN' => UserFixtures::DEFAULT_API_TOKEN,
]);
break;
default:
throw new \Exception(sprintf('Unknown role "%s"', $role));
break;
}
return $client;
}
/**
* @param string $url
* @param bool $json
* @return string
*/
protected function createUrl($url, $json = true)
{
return '/' . ltrim($url, '/') . ($json ? '.json' : '');
}
protected function assertRequestIsSecured(Client $client, string $url, $method = 'GET')
{
$this->request($client, $url, $method);
$this->assertResponseIsSecured($client->getResponse(), $url);
}
/**
* @param Response $response
* @param string $url
*/
protected function assertResponseIsSecured(Response $response, string $url)
{
$data = ['message' => 'Authentication required, missing headers: X-AUTH-USER, X-AUTH-TOKEN'];
self::assertEquals(
$data,
json_decode($response->getContent(), true),
sprintf('The secure URL %s is not protected.', $url)
);
self::assertEquals(
Response::HTTP_FORBIDDEN,
$response->getStatusCode(),
sprintf('The secure URL %s has the wrong status code %s.', $url, $response->getStatusCode())
);
}
/**
* @param string $role
* @param string $url
* @param string $method
*/
protected function assertUrlIsSecuredForRole(string $role, string $url, string $method = 'GET')
{
$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)
);
$expected = [
'code' => 403,
'message' => 'Access denied.'
];
self::assertEquals(403, $client->getResponse()->getStatusCode());
self::assertEquals(
$expected,
json_decode($client->getResponse()->getContent(), true)
);
}
protected function request(Client $client, string $url, $method = 'GET', array $parameters = [], string $content = null): Crawler
{
$server = ['HTTP_CONTENT_TYPE' => 'application/json', 'CONTENT_TYPE' => 'application/json'];
return $client->request($method, $this->createUrl($url), $parameters, [], $server, $content);
}
protected function assertEntityNotFound(string $role, string $url, string $method = 'GET')
{
$client = $this->getClientForAuthenticatedUser($role);
$this->request($client, $url, $method);
$expected = [
'code' => 404,
'message' => 'Not found'
];
self::assertEquals(404, $client->getResponse()->getStatusCode());
self::assertEquals(
$expected,
json_decode($client->getResponse()->getContent(), true)
);
}
protected function assertEntityNotFoundForPatch(string $role, string $url, array $data)
{
return $this->assertExceptionForPatchAction($role, $url, $data, [
'code' => 404,
'message' => 'Not found'
]);
}
protected function assertExceptionForPatchAction(string $role, string $url, array $data, array $expectedErrors)
{
$client = $this->getClientForAuthenticatedUser($role);
$this->request($client, $url, 'PATCH', [], json_encode($data));
$response = $client->getResponse();
self::assertFalse($response->isSuccessful());
self::assertEquals($expectedErrors['code'], $client->getResponse()->getStatusCode());
self::assertEquals(
$expectedErrors,
json_decode($client->getResponse()->getContent(), true)
);
}
protected function assertEntityNotFoundForDelete(string $role, string $url, array $data)
{
$client = $this->getClientForAuthenticatedUser($role);
$this->request($client, $url, 'DELETE', [], json_encode($data));
$response = $client->getResponse();
self::assertFalse($response->isSuccessful());
$expected = [
'code' => 404,
'message' => 'Not found'
];
self::assertEquals(404, $client->getResponse()->getStatusCode());
self::assertEquals(
$expected,
json_decode($client->getResponse()->getContent(), true)
);
}
protected function assertApiException(Response $response, string $message)
{
self::assertFalse($response->isSuccessful());
self::assertEquals(500, $response->getStatusCode());
self::assertEquals(['code' => 500, 'message' => $message], json_decode($response->getContent(), true));
}
protected function assertApiAccessDenied(Client $client, string $url, string $message)
{
$this->request($client, $url);
$this->assertApiResponseAccessDenied($client->getResponse(), $message);
}
protected function assertApiResponseAccessDenied(Response $response, string $message)
{
self::assertFalse($response->isSuccessful());
self::assertEquals(Response::HTTP_FORBIDDEN, $response->getStatusCode());
$expected = ['code' => Response::HTTP_FORBIDDEN, 'message' => $message];
self::assertEquals($expected, json_decode($response->getContent(), true));
}
/**
* @param Response $response
* @param string[] $failedFields
* @param bool $extraFields
*/
protected function assertApiCallValidationError(Response $response, array $failedFields, bool $extraFields = false)
{
self::assertFalse($response->isSuccessful());
$result = json_decode($response->getContent(), true);
self::assertArrayHasKey('errors', $result);
if ($extraFields) {
self::assertArrayHasKey('errors', $result['errors']);
self::assertEquals($result['errors']['errors'][0], 'This form should not contain extra fields.');
}
self::assertArrayHasKey('children', $result['errors']);
$data = $result['errors']['children'];
foreach ($failedFields as $fieldName) {
self::assertArrayHasKey($fieldName, $data);
self::assertArrayHasKey('errors', $data[$fieldName]);
}
}
}