Abstract all project test to BaseTest

This commit is contained in:
cmorenov1402
2025-04-01 10:55:06 +02:00
parent 3e26e5b6f8
commit 27026666cc
7 changed files with 126 additions and 164 deletions
+32 -64
View File
@@ -5,11 +5,12 @@ namespace App\Tests\Entity\ProjectApi;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Symfony\Bundle\Test\Client;
use App\Entity\Project\Category;
use App\Entity\Project\Project;
use App\Entity\Project\ProjectDeadline;
use App\Entity\Project\ProjectStatus;
use App\Entity\Project\ProjectTerritory;
use App\Entity\User\User;
use App\Factory\Project\ProjectFactory;
use App\Factory\User\UserFactory;
use App\Tests\Traits\TestHelperTrait;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
use Zenstruck\Foundry\Test\Factories;
@@ -19,14 +20,17 @@ abstract class BaseTest extends ApiTestCase
{
use ResetDatabase;
use Factories;
use TestHelperTrait;
protected EntityManagerInterface $entityManager;
private const USER_EMAIL = 'testuser@example.com';
private const USER_PASSWORD = 'projectapitestuserpassword';
private const BASE_URI = '/v4/projects';
protected const BASE_URI = '/v4/projects';
public function setUp(): void
{
parent::setUp();
self::bootKernel();
$this->entityManager = static::getContainer()->get(EntityManagerInterface::class);
@@ -49,25 +53,20 @@ abstract class BaseTest extends ApiTestCase
return self::BASE_URI.$param;
}
protected function getRequestOptions(Client $client)
{
return ['headers' => $this->getHeaders($client)];
}
protected function createTestUser(
string $handle = 'test_user',
string $email = self::USER_EMAIL,
): User {
$user = new User();
$user->setHandle($handle);
$user->setEmail($email);
$passwordHasher = static::getContainer()->get('security.user_password_hasher');
$user->setPassword($passwordHasher->hashPassword($user, self::USER_PASSWORD));
return $user;
}
protected function prepareTestUser(?User $user = null): void
{
$user ??= $this->createTestUser();
$this->entityManager->persist($user);
$this->entityManager->flush();
) {
return UserFactory::createOne([
'handle' => $handle,
'email' => $email,
'password' => self::USER_PASSWORD,
]);
}
protected function getExampleProjectData(): array
@@ -84,60 +83,31 @@ abstract class BaseTest extends ApiTestCase
];
}
protected function createTestProject(): Project
protected function createTestProjectOptimized(int $count = 1, array $attributes = []): array
{
$example = $this->getExampleProjectData();
$owner = $this->createTestUser();
$territory = new ProjectTerritory('ES');
$project = new Project();
$project->setTitle($example['title']);
$project->setSubtitle($example['subtitle']);
$project->setCategory($example['category']);
$project->setTerritory(new ProjectTerritory($example['territory']['country']));
$project->setDescription($example['description']);
$project->setDeadline($example['deadline']);
$project->setOwner($this->createTestUser());
$project->setStatus($example['status']);
$mergedAttributes = array_merge([
'owner' => $owner,
'territory' => $territory,
], $attributes);
return $project;
}
protected function prepareTestProject(?Project $project = null): void
{
$project ??= $this->createTestProject();
$this->entityManager->persist($project);
$this->entityManager->flush();
}
protected function getValidToken(Client $client): string
{
$client->request(
'POST',
'/v4/user_tokens',
[
'json' => [
'identifier' => self::USER_EMAIL,
'password' => self::USER_PASSWORD,
],
]
);
return json_decode($client->getResponse()->getContent(), true)['token'];
return ProjectFactory::createMany($count, $mergedAttributes);
}
protected function getHeaders(Client $client): array
{
return [
'Authorization' => 'Bearer '.$this->getValidToken($client),
'Content-Type' => 'application/json',
];
$method = $this->getMethod();
return $this->getAuthHeaders($client, self::USER_EMAIL, self::USER_PASSWORD, $method);
}
// Auxiliary Tests
protected function testOneNotFound(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized(1);
$client = static::createClient();
$client->request(
@@ -184,15 +154,13 @@ abstract class BaseTest extends ApiTestCase
protected function testForbidden(): void
{
$otherUser = $this->createTestUser('other_user', 'otheruser@example.com');
$otherProject = $this->createTestProject()->setOwner($otherUser);
$this->entityManager->persist($otherProject);
$this->prepareTestUser();
$this->createTestProjectOptimized(1, ['owner' => $otherUser]);
$client = static::createClient();
$client->request(
$this->getMethod(),
$this->getUri(1),
['headers' => $this->getHeaders($client)]
$this->getRequestOptions($client)
);
$this->assertResponseStatusCodeSame(Response::HTTP_FORBIDDEN);
+9 -14
View File
@@ -2,13 +2,10 @@
namespace App\Tests\Entity\ProjectApi;
use ApiPlatform\Symfony\Bundle\Test\Client;
use Symfony\Component\HttpFoundation\Response;
class CreateTest extends BaseTest
{
private const URI = '/v4/projects';
// Auxiliary functions
protected function getMethod(): string
@@ -16,13 +13,6 @@ class CreateTest extends BaseTest
return 'POST';
}
protected function getHeaders(Client $client): array
{
$this->prepareTestUser();
return parent::getHeaders($client);
}
private function assertProjectData(array $expectedData, array $responseData): void
{
$this->assertArrayHasKey('id', $responseData);
@@ -60,7 +50,8 @@ class CreateTest extends BaseTest
$requestData = array_merge($requestData, $setData);
$this->testInsert($requestData, self::URI, $expectedCode);
$this->createTestUser();
$this->testInsert($requestData, self::BASE_URI, $expectedCode);
}
private function testPostWithInvalidInput(array $invalidData): void
@@ -79,6 +70,8 @@ class CreateTest extends BaseTest
public function testPostWithValidToken(): void
{
$this->createTestUser();
$expectedData = [
'title' => 'New Education Project',
'subtitle' => 'Education for the Future',
@@ -90,7 +83,7 @@ class CreateTest extends BaseTest
];
$client = static::createClient();
$client->request('POST', self::URI, [
$client->request('POST', self::BASE_URI, [
'headers' => $this->getHeaders($client),
'json' => $expectedData,
]);
@@ -102,6 +95,8 @@ class CreateTest extends BaseTest
public function testPostWithoutMandatoryField(): void
{
$this->createTestUser();
// Expected data without the 'title' field
$requestData = [
'subtitle' => 'Education for the Future',
@@ -113,7 +108,7 @@ class CreateTest extends BaseTest
];
$client = static::createClient();
$client->request('POST', self::URI, [
$client->request('POST', self::BASE_URI, [
'headers' => $this->getHeaders($client),
'json' => $requestData,
]);
@@ -154,7 +149,7 @@ class CreateTest extends BaseTest
$client->request(
'POST',
self::URI,
self::BASE_URI,
[
'json' => [
'title' => 'ProjectApiTest Project',
+3 -3
View File
@@ -15,17 +15,17 @@ class DeleteTest extends BaseTest
public function testDeleteWithValidToken(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized();
$client = static::createClient();
$client->request('DELETE', $this->getUri(1), ['headers' => $this->getHeaders($client)]);
$client->request('DELETE', $this->getUri(1), $this->getRequestOptions($client));
$this->assertResponseStatusCodeSame(Response::HTTP_NO_CONTENT);
}
public function testDeleteUnauthorized()
{
$this->prepareTestProject();
$this->createTestProjectOptimized();
static::createClient()->request('DELETE', $this->getUri(1));
+20 -66
View File
@@ -2,79 +2,29 @@
namespace App\Tests\Entity\ProjectApi;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use ApiPlatform\Symfony\Bundle\Test\Client;
use App\Entity\Project\Category;
use App\Entity\Project\ProjectStatus;
use App\Entity\Project\ProjectTerritory;
use App\Factory\Project\ProjectFactory;
use App\Factory\User\UserFactory;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;
class GetAllTest extends ApiTestCase
class GetAllTest extends BaseTest
{
use ResetDatabase;
use Factories;
protected EntityManagerInterface $entityManager;
private const USER_EMAIL = 'testuser@example.com';
private const USER_PASSWORD = 'projectapitestuserpassword';
private const BASE_URI = '/v4/projects';
private const METHOD = 'GET';
private const PAGE_SIZE = 30;
public function setUp(): void
{
self::bootKernel();
$this->entityManager = static::getContainer()->get(EntityManagerInterface::class);
parent::setUp();
}
// Auxiliary functions
private function createTestUser()
protected function getMethod(): string
{
return UserFactory::createOne([
'email' => self::USER_EMAIL,
'password' => self::USER_PASSWORD,
]);
}
private function createTestProjectOptimized(int $count, array $attributes = [])
{
$owner = $this->createTestUser();
$territory = new ProjectTerritory('ES');
$mergedAttributes = array_merge([
'owner' => $owner,
'territory' => $territory,
], $attributes);
ProjectFactory::createMany($count, $mergedAttributes);
}
private function getHeaders(Client $client)
{
// Responsability 1: Get Token
$client->request(
'POST',
'/v4/user_tokens',
[
'json' => [
'identifier' => self::USER_EMAIL,
'password' => self::USER_PASSWORD,
],
]
);
$token = json_decode($client->getResponse()->getContent(), true)['token'];
// Responsability 2 : Return headers
return ['headers' => ['Authorization' => "Bearer $token"]];
return 'GET';
}
private function getMinNumInPage($page = 1, $pageSize = self::PAGE_SIZE)
@@ -114,7 +64,7 @@ class GetAllTest extends ApiTestCase
$uri = self::BASE_URI."?$param=$valueName";
$client = static::createClient();
$client->request(self::METHOD, $uri, $this->getHeaders($client));
$client->request($this->getMethod(), $uri, $this->getRequestOptions($client));
$this->assertResponseStatusCodeSame($responseCode);
@@ -145,7 +95,7 @@ class GetAllTest extends ApiTestCase
$uri = self::BASE_URI.'?'.$queryParams;
$client = static::createClient();
$client->request(self::METHOD, $uri, $this->getHeaders($client));
$client->request($this->getMethod(), $uri, $this->getRequestOptions($client));
$this->assertResponseIsSuccessful();
@@ -162,7 +112,11 @@ class GetAllTest extends ApiTestCase
ProjectFactory::createMany($numberOfProjects, ['owner' => $owner]);
$client = static::createClient();
$client->request(self::METHOD, self::BASE_URI, $this->getHeaders($client));
$client->request(
$$this->getMethod()(),
self::BASE_URI,
['headers' => $this->getHeaders($client)]
);
$this->assertResponseIsSuccessful();
@@ -182,9 +136,9 @@ class GetAllTest extends ApiTestCase
$client = static::createClient();
$client->request(
self::METHOD,
$this->getMethod(),
self::BASE_URI."?page=$page&itemsPerPage=$itemsPerPage",
$this->getHeaders($client)
['headers' => $this->getHeaders($client)]
);
$this->assertResponseIsSuccessful();
@@ -205,9 +159,9 @@ class GetAllTest extends ApiTestCase
$client = static::createClient();
$client->request(
self::METHOD,
$this->getMethod(),
self::BASE_URI."?itemsPerPage=$itemsPerPage",
$this->getHeaders($client)
['headers' => $this->getHeaders($client)]
);
$this->assertResponseIsSuccessful();
@@ -241,7 +195,7 @@ class GetAllTest extends ApiTestCase
$category = 'invalid_category';
$uri = self::BASE_URI."?category=$category";
$client = static::createClient();
$client->request(self::METHOD, $uri, $this->getHeaders($client));
$client->request($this->getMethod(), $uri, ['headers' => $this->getHeaders($client)]);
$responseCode = Response::HTTP_OK;
$this->assertResponseStatusCodeSame($responseCode);
@@ -260,7 +214,7 @@ class GetAllTest extends ApiTestCase
$uri = self::BASE_URI.'?title=NotFound';
$client = static::createClient();
$client->request(self::METHOD, $uri, $this->getHeaders($client));
$client->request($this->getMethod(), $uri, ['headers' => $this->getHeaders($client)]);
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
@@ -311,7 +265,7 @@ class GetAllTest extends ApiTestCase
$this->createTestProjectOptimized(1);
$client = static::createClient();
$client->request('GET', self::BASE_URI, $this->getHeaders($client));
$client->request('GET', self::BASE_URI, ['headers' => $this->getHeaders($client)]);
$this->assertResponseIsSuccessful();
@@ -330,7 +284,7 @@ class GetAllTest extends ApiTestCase
public function testGetAllUnauthorized(): void
{
static::createClient()->request(self::METHOD, self::BASE_URI);
static::createClient()->request($this->getMethod(), self::BASE_URI);
$this->assertResponseIsSuccessful();
}
@@ -338,7 +292,7 @@ class GetAllTest extends ApiTestCase
public function testGetAllWithInvalidToken(): void
{
static::createClient()->request(
self::METHOD,
$this->getMethod(),
self::BASE_URI,
['headers' => ['Authorization' => 'Bearer 123']]
);
+3 -5
View File
@@ -42,8 +42,6 @@ class GetOneTest extends BaseTest
private function testSuccessfulGetOneBase(Project $project): void
{
$this->prepareTestProject($project);
$client = static::createClient();
$client->request('GET', $this->getUri(1), ['headers' => $this->getHeaders($client)]);
@@ -54,7 +52,7 @@ class GetOneTest extends BaseTest
private function testGetOneFilteredByStatus(ProjectStatus $status): void
{
$project = $this->createTestProject()->setStatus($status);
$project = $this->createTestProjectOptimized(1, ['status' => $status])[0];
$this->testSuccessfulGetOneBase($project);
}
@@ -63,7 +61,7 @@ class GetOneTest extends BaseTest
public function testGetOneWithValidToken(): void
{
$project = $this->createTestProject();
$project = $this->createTestProjectOptimized(1)[0];
$this->testSuccessfulGetOneBase($project);
}
@@ -80,7 +78,7 @@ class GetOneTest extends BaseTest
public function testGetOneUnauthorized(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized(1);
static::createClient()->request('GET', $this->getUri(1));
+3 -12
View File
@@ -2,7 +2,6 @@
namespace App\Tests\Entity\ProjectApi;
use ApiPlatform\Symfony\Bundle\Test\Client;
use Symfony\Component\HttpFoundation\Response;
class UpdateTest extends BaseTest
@@ -14,19 +13,11 @@ class UpdateTest extends BaseTest
return 'PATCH';
}
protected function getHeaders(Client $client): array
{
return [
'Authorization' => 'Bearer '.$this->getValidToken($client),
'Content-Type' => 'application/merge-patch+json',
];
}
// Runable Tests
public function testUpdateSuccessful(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized();
$dataToModify = [
'title' => 'New project title',
@@ -38,7 +29,7 @@ class UpdateTest extends BaseTest
public function testUpdateUnauthorized(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized();
static::createClient()->request($this->getMethod(), $this->getUri(1));
@@ -57,7 +48,7 @@ class UpdateTest extends BaseTest
public function testUpdateInvalidInput(): void
{
$this->prepareTestProject();
$this->createTestProjectOptimized();
$invalidInput = [
'title' => 'New project title',
'category' => 'invalid-category',
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace App\Tests\Traits;
use ApiPlatform\Symfony\Bundle\Test\Client;
use Symfony\Component\HttpFoundation\Response;
trait TestHelperTrait
{
protected function getValidToken(Client $client, string $email, string $password): string
{
$client->request(
'POST',
'/v4/user_tokens',
[
'json' => [
'identifier' => $email,
'password' => $password,
],
]
);
return json_decode($client->getResponse()->getContent(), true)['token'];
}
protected function getAuthHeaders(
Client $client,
string $email,
string $password,
string $method = 'GET',
): array {
$contentType = $method == 'PATCH' ? 'application/merge-patch+json' : 'application/json';
return [
'Authorization' => 'Bearer '.$this->getValidToken($client, $email, $password),
'Content-Type' => $contentType,
];
}
protected function testInvalidToken(
string $uri,
string $contentType = 'application/json',
int $expectedToken = Response::HTTP_UNAUTHORIZED,
): void {
static::createClient()->request(
$this->getMethod(),
$uri,
['headers' => [
'Authorization' => 'Bearer invalid_token',
'Content-Type' => $contentType,
]]
);
$this->assertResponseStatusCodeSame($expectedToken);
}
}