|
@@ -2,33 +2,134 @@
|
|
|
|
|
|
|
|
namespace App\Tests\Application;
|
|
namespace App\Tests\Application;
|
|
|
|
|
|
|
|
|
|
+use App\Entity\Access\Access;
|
|
|
|
|
+use App\Entity\Person\Person;
|
|
|
use App\Entity\Public\FederationStructure;
|
|
use App\Entity\Public\FederationStructure;
|
|
|
|
|
+use App\Enum\Organization\LegalEnum;
|
|
|
|
|
+use App\Enum\Organization\PrincipalTypeEnum;
|
|
|
|
|
+use App\Enum\Organization\SettingsProductEnum;
|
|
|
|
|
+use App\Tests\Fixture\Factory\Access\AccessFactory;
|
|
|
|
|
+use App\Tests\Fixture\Factory\Organization\OrganizationFactory;
|
|
|
|
|
+use App\Tests\Fixture\Factory\Organization\SettingsFactory;
|
|
|
|
|
+use App\Tests\Fixture\Factory\Person\PersonFactory;
|
|
|
|
|
+use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
+use Doctrine\Common\DataFixtures\Purger\ORMPurger;
|
|
|
|
|
+use Symfony\Bundle\SecurityBundle\Security;
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
use Symfony\Component\DomCrawler\Crawler;
|
|
use Symfony\Component\DomCrawler\Crawler;
|
|
|
use ApiPlatform\Symfony\Bundle\Test\Client;
|
|
use ApiPlatform\Symfony\Bundle\Test\Client;
|
|
|
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
|
|
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
|
|
|
use Symfony\Contracts\HttpClient\ResponseInterface;
|
|
use Symfony\Contracts\HttpClient\ResponseInterface;
|
|
|
|
|
+use Zenstruck\Foundry\Proxy;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Base class for applicative tests
|
|
* Base class for applicative tests
|
|
|
*/
|
|
*/
|
|
|
abstract class OtWebTestCase extends ApiTestCase
|
|
abstract class OtWebTestCase extends ApiTestCase
|
|
|
{
|
|
{
|
|
|
|
|
+ protected EntityManagerInterface $em;
|
|
|
protected Client $client;
|
|
protected Client $client;
|
|
|
|
|
+ protected Access | Proxy | null $user = null;
|
|
|
|
|
+ protected ?string $securityToken = null;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Executed before each test
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return void
|
|
|
|
|
+ * @throws \Exception
|
|
|
|
|
+ */
|
|
|
public function setup(): void {
|
|
public function setup(): void {
|
|
|
|
|
+
|
|
|
|
|
+ // Boot le kernel symfony et récupère l'entity manager
|
|
|
|
|
+ // @see https://symfony.com/doc/current/testing.html#retrieving-services-in-the-test
|
|
|
|
|
+ self::bootKernel();
|
|
|
|
|
+ $this->em = static::getContainer()->get(EntityManagerInterface::class);
|
|
|
|
|
+
|
|
|
|
|
+ // Purge DB before populating new fixtures
|
|
|
|
|
+ $this->purgeDb();
|
|
|
|
|
+
|
|
|
|
|
+ // Définit les fixtures et flush
|
|
|
|
|
+ $this->loadFixture();
|
|
|
|
|
+ $this->em->flush();
|
|
|
|
|
+
|
|
|
|
|
+ // Instancie le client qui exécutera les requêtes à l'api
|
|
|
|
|
+ // @see https://symfony.com/doc/current/testing.html#making-requests
|
|
|
$this->client = static::createClient();
|
|
$this->client = static::createClient();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Delete all DB records before populating fixtures.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return void
|
|
|
|
|
+ * @throws \Doctrine\DBAL\Exception
|
|
|
|
|
+ */
|
|
|
|
|
+ private function purgeDb() {
|
|
|
|
|
+ if (!preg_match('/.*test.*/', $this->em->getConnection()->getDatabase())) {
|
|
|
|
|
+ throw new \RuntimeException("The DB name shall contain 'test' in its name to be purge");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $this->em->getConnection()->exec('SET FOREIGN_KEY_CHECKS = 0;');
|
|
|
|
|
+ $purger = new ORMPurger($this->em);
|
|
|
|
|
+ $purger->setPurgeMode(ORMPurger::PURGE_MODE_DELETE);
|
|
|
|
|
+ $purger->purge();
|
|
|
|
|
+ $this->em->getConnection()->exec('SET FOREIGN_KEY_CHECKS = 1;');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Create and persist the fixtures (do not flush)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#same-entities-used-in-these-docs
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return void
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function loadFixture(): void {
|
|
|
|
|
+ $person = PersonFactory::createOne(
|
|
|
|
|
+ [
|
|
|
|
|
+ 'username' => 'username',
|
|
|
|
|
+ 'password' => 'password'
|
|
|
|
|
+ ]
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ $organization = OrganizationFactory::createOne([
|
|
|
|
|
+ 'legalStatus' => LegalEnum::ASSOCIATION_LAW_1901()->getValue(),
|
|
|
|
|
+ 'principalType' => PrincipalTypeEnum::ARTISTIC_EDUCATION_ONLY()->getValue(),
|
|
|
|
|
+ 'name' => 'My Organization'
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ SettingsFactory::createOne([
|
|
|
|
|
+ 'product' => SettingsProductEnum::ARTIST(),
|
|
|
|
|
+ 'organization' => $organization
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $this->user = AccessFactory::createOne([
|
|
|
|
|
+ 'person' => $person,
|
|
|
|
|
+ 'organization' => $organization,
|
|
|
|
|
+ 'roles' => ['ROLE_USERS_VIEW']
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Send a requests, parse the hydra response and return an object or a Collection
|
|
* Send a requests, parse the hydra response and return an object or a Collection
|
|
|
*
|
|
*
|
|
|
* @param string $method
|
|
* @param string $method
|
|
|
* @param string $route
|
|
* @param string $route
|
|
|
- * @param array<mixed> $parameters
|
|
|
|
|
|
|
+ * @param array<mixed> $data
|
|
|
|
|
+ * @param array<mixed> $headers
|
|
|
* @return ResponseInterface
|
|
* @return ResponseInterface
|
|
|
*/
|
|
*/
|
|
|
- protected function request(string $method, string $route, array $parameters = []): ResponseInterface {
|
|
|
|
|
|
|
+ protected function request(string $method, string $route, array | null $data = null, array $headers = []): ResponseInterface {
|
|
|
|
|
+ if ($this->user) {
|
|
|
|
|
+ $headers = array_merge(
|
|
|
|
|
+ ['x-accessid' => $this->user->getId(), 'authorization' => 'BEARER ' . $this->securityToken],
|
|
|
|
|
+ $headers
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $parameters = ['headers' => $headers];
|
|
|
|
|
+ if ($data) {
|
|
|
|
|
+ $parameters['json'] = $data;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return $this->client->request(
|
|
return $this->client->request(
|
|
|
$method,
|
|
$method,
|
|
|
$route,
|
|
$route,
|
|
@@ -40,19 +141,104 @@ abstract class OtWebTestCase extends ApiTestCase
|
|
|
* Send a GET request and return the response parsed content
|
|
* Send a GET request and return the response parsed content
|
|
|
*
|
|
*
|
|
|
* @param string $route
|
|
* @param string $route
|
|
|
- * @param array<mixed> $parameters
|
|
|
|
|
|
|
+ * @param array<mixed> $headers
|
|
|
* @return ResponseInterface
|
|
* @return ResponseInterface
|
|
|
*/
|
|
*/
|
|
|
- protected function get(string $route, array $parameters = []): ResponseInterface {
|
|
|
|
|
|
|
+ protected function get(string $route, array $headers = []): ResponseInterface {
|
|
|
return $this->request(
|
|
return $this->request(
|
|
|
Request::METHOD_GET,
|
|
Request::METHOD_GET,
|
|
|
$route,
|
|
$route,
|
|
|
- $parameters
|
|
|
|
|
|
|
+ null,
|
|
|
|
|
+ $headers
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- protected function validateCollectionSchema(string $resourceClass): void {
|
|
|
|
|
- $this->assertResponseIsSuccessful();
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Send a PUT request and return the response parsed content
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $route
|
|
|
|
|
+ * @param array<mixed> $data
|
|
|
|
|
+ * @param array<mixed> $headers
|
|
|
|
|
+ * @return ResponseInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function put(string $route, array $data, array $headers = []): ResponseInterface {
|
|
|
|
|
+ return $this->request(
|
|
|
|
|
+ Request::METHOD_PUT,
|
|
|
|
|
+ $route,
|
|
|
|
|
+ $data,
|
|
|
|
|
+ $headers
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Send a POST request and return the response parsed content
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $route
|
|
|
|
|
+ * @param array<mixed> $data
|
|
|
|
|
+ * @param array<mixed> $headers
|
|
|
|
|
+ * @return ResponseInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function post(string $route, array $data, array $headers = []): ResponseInterface {
|
|
|
|
|
+ return $this->request(
|
|
|
|
|
+ Request::METHOD_POST,
|
|
|
|
|
+ $route,
|
|
|
|
|
+ $data,
|
|
|
|
|
+ $headers
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Send a DELETE request and return the response parsed content
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $route
|
|
|
|
|
+ * @param array<mixed> $headers
|
|
|
|
|
+ * @return ResponseInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function delete(string $route, array $headers = []): ResponseInterface {
|
|
|
|
|
+ return $this->request(
|
|
|
|
|
+ Request::METHOD_DELETE,
|
|
|
|
|
+ $route,
|
|
|
|
|
+ null,
|
|
|
|
|
+ $headers
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Login as the given Access user
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param Proxy|Access $access
|
|
|
|
|
+ * @return void
|
|
|
|
|
+ * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
|
|
|
|
+ * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
|
|
|
|
+ * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
|
|
|
|
+ * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function loginAs(Proxy | Access $access): void {
|
|
|
|
|
+ $person = $access->getPerson();
|
|
|
|
|
+
|
|
|
|
|
+ $response = $this->post(
|
|
|
|
|
+ '/login_check',
|
|
|
|
|
+ ['username' => $person->getUsername(), 'password' => $person->getPassword()]
|
|
|
|
|
+ );
|
|
|
|
|
+ $content = $response->getContent();
|
|
|
|
|
+
|
|
|
|
|
+ $this->securityToken = json_decode($content)->token;
|
|
|
|
|
+ $this->user = $access;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Assert that the response has the expected status code and is well formated
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $resourceClass
|
|
|
|
|
+ * @param int $expectedStatus
|
|
|
|
|
+ * @return void
|
|
|
|
|
+ */
|
|
|
|
|
+ protected function validateCollectionSchema(string $resourceClass, int $expectedStatus = 200): void {
|
|
|
|
|
+ $this->assertResponseStatusCodeSame($expectedStatus);
|
|
|
|
|
+
|
|
|
|
|
+ if ($expectedStatus == 200) {
|
|
|
|
|
+ $this->assertResponseIsSuccessful();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Asserts that the returned content type is JSON-LD (the default)
|
|
// Asserts that the returned content type is JSON-LD (the default)
|
|
|
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
|
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
|
@@ -61,5 +247,4 @@ abstract class OtWebTestCase extends ApiTestCase
|
|
|
// >>> Issue with the json typed PublicStructure::addresses properties
|
|
// >>> Issue with the json typed PublicStructure::addresses properties
|
|
|
// $this->assertMatchesResourceCollectionJsonSchema($resourceClass);
|
|
// $this->assertMatchesResourceCollectionJsonSchema($resourceClass);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
}
|
|
}
|