From 27026666cc687299e7e46faa46e72de807faaee2 Mon Sep 17 00:00:00 2001 From: cmorenov1402 Date: Tue, 1 Apr 2025 10:55:06 +0200 Subject: [PATCH] Abstract all project test to BaseTest --- tests/Entity/ProjectApi/BaseTest.php | 96 +++++++++----------------- tests/Entity/ProjectApi/CreateTest.php | 23 +++--- tests/Entity/ProjectApi/DeleteTest.php | 6 +- tests/Entity/ProjectApi/GetAllTest.php | 86 ++++++----------------- tests/Entity/ProjectApi/GetOneTest.php | 8 +-- tests/Entity/ProjectApi/UpdateTest.php | 15 +--- tests/Traits/TestHelperTrait.php | 56 +++++++++++++++ 7 files changed, 126 insertions(+), 164 deletions(-) create mode 100644 tests/Traits/TestHelperTrait.php diff --git a/tests/Entity/ProjectApi/BaseTest.php b/tests/Entity/ProjectApi/BaseTest.php index 915f080..10b9110 100644 --- a/tests/Entity/ProjectApi/BaseTest.php +++ b/tests/Entity/ProjectApi/BaseTest.php @@ -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); diff --git a/tests/Entity/ProjectApi/CreateTest.php b/tests/Entity/ProjectApi/CreateTest.php index 22a6887..bccdd16 100644 --- a/tests/Entity/ProjectApi/CreateTest.php +++ b/tests/Entity/ProjectApi/CreateTest.php @@ -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', diff --git a/tests/Entity/ProjectApi/DeleteTest.php b/tests/Entity/ProjectApi/DeleteTest.php index 9e577e8..f0b13af 100644 --- a/tests/Entity/ProjectApi/DeleteTest.php +++ b/tests/Entity/ProjectApi/DeleteTest.php @@ -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)); diff --git a/tests/Entity/ProjectApi/GetAllTest.php b/tests/Entity/ProjectApi/GetAllTest.php index 66f4bd2..456e439 100644 --- a/tests/Entity/ProjectApi/GetAllTest.php +++ b/tests/Entity/ProjectApi/GetAllTest.php @@ -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']] ); diff --git a/tests/Entity/ProjectApi/GetOneTest.php b/tests/Entity/ProjectApi/GetOneTest.php index dea3bf7..5e7ece4 100644 --- a/tests/Entity/ProjectApi/GetOneTest.php +++ b/tests/Entity/ProjectApi/GetOneTest.php @@ -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)); diff --git a/tests/Entity/ProjectApi/UpdateTest.php b/tests/Entity/ProjectApi/UpdateTest.php index d8e04c3..5429c7a 100644 --- a/tests/Entity/ProjectApi/UpdateTest.php +++ b/tests/Entity/ProjectApi/UpdateTest.php @@ -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', diff --git a/tests/Traits/TestHelperTrait.php b/tests/Traits/TestHelperTrait.php new file mode 100644 index 0000000..5506e2f --- /dev/null +++ b/tests/Traits/TestHelperTrait.php @@ -0,0 +1,56 @@ +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); + } +}