Просмотр исходного кода

add unit tests for api repositories

Olivier Massot 4 лет назад
Родитель
Сommit
ce51319517

+ 73 - 0
ot_core/Tests/Unit/Domain/Repository/AbstractApiRepositoryTestCase.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
+
+use GuzzleHttp\Client;
+use Nimut\TestingFramework\TestCase\UnitTestCase;
+use Opentalent\OtCore\Domain\Repository\BaseApiRepository;
+use Opentalent\OtCore\Tests\Unit\Fixtures\ApiResponseFixtures;
+use ReflectionClass;
+use TYPO3\CMS\Core\Core\ApplicationContext;
+
+/**
+ * Base class for BaseApiRepositoryTest and its subclasses
+ *
+ * @package Opentalent\OtCore\Tests\Unit\Repository
+ */
+abstract class AbstractApiRepositoryTestCase extends UnitTestCase
+{
+    const TESTED_CLASS = '';
+
+    protected $context;
+    /**
+     * @var ApiResponseFixtures
+     */
+    protected $fixture;
+    /**
+     * @var object
+     */
+    protected $repository;
+    /**
+     * @var \Prophecy\Prophecy\ObjectProphecy
+     */
+    protected $client;
+
+    public function setUp() {
+        // mock the application context
+        $this->context = $this->prophesize(ApplicationContext::class);
+        $this->context->isProduction()->willReturn(true);
+
+        $this->client = $this->prophesize(Client::class);
+
+        $repositoryClass = new ReflectionClass(static::TESTED_CLASS);
+        foreach ($repositoryClass->getMethods() as $method) {
+            $method->setAccessible(true);
+        }
+        $this->repository = $repositoryClass->newInstanceArgs([$this->client->reveal(), $this->context->reveal()]);
+
+        $this->fixture = new ApiResponseFixtures();
+    }
+
+    protected function injectClientFor($uri) {
+        // mock the Guzzle client
+        $willReturn = $this->fixture->get($uri);
+        $client = $this->prophesize(Client::class);
+        $client->request(BaseApiRepository::HTTP_METHOD, $uri)
+            ->shouldBeCalled()
+            ->willReturn($willReturn);
+
+        $reflectionObject = new \ReflectionObject($this->repository);
+        $reflectionMethod = $reflectionObject->getMethod('injectClient');
+        $reflectionMethod->setAccessible(true);
+
+        $reflectionMethod->invokeArgs($this->repository, [$client->reveal()]);
+    }
+
+    protected function callMemberToObject(array $record) {
+        $reflectionObject = new \ReflectionObject($this->repository);
+        $reflectionMethod = $reflectionObject->getMethod('memberToObject');
+        $reflectionMethod->setAccessible(true);
+
+        return $reflectionMethod->invokeArgs($this->repository, [$record]);
+    }
+}

+ 2 - 1
ot_core/Tests/Unit/Domain/Repository/ApiPagedCollectionTest.php

@@ -1,8 +1,9 @@
 <?php
 
-namespace Opentalent\OtCore\Domain\Repository;
+namespace Opentalent\OtCore\Tests\Unit\Repository;
 
 use Nimut\TestingFramework\TestCase\UnitTestCase;
+use Opentalent\OtCore\Domain\Repository\ApiPagedCollection;
 
 class ApiPagedCollectionTest extends UnitTestCase
 {

+ 16 - 48
ot_core/Tests/Unit/Domain/Repository/BaseApiRepositoryTest.php

@@ -1,14 +1,15 @@
 <?php
 
-namespace Opentalent\OtCore\Tests\Unit\Repository;
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
 
-use Nimut\TestingFramework\TestCase\UnitTestCase;
-use Opentalent\OtCore\Domain\Repository\BaseApiRepository;
 use GuzzleHttp\Client;
+use Opentalent\OtCore\Domain\Repository\BaseApiRepository;
 use Opentalent\OtCore\Exception\ApiRequestException;
-use Opentalent\OtCore\Tests\Unit\Fixtures\ApiResponseFixtures;
-use TYPO3\CMS\Core\Core\ApplicationContext;
 
+/**
+ * Proxy to reveal the private methods of the abstract class BaseApiRepository
+ * @package Opentalent\OtCore\Tests\Unit\Domain\Repository
+ */
 class ConcreteBaseApiRepository extends BaseApiRepository {
     protected function memberToObject(array $member) { return $member; }
     public function injectClient($client) { parent::injectClient($client); }
@@ -19,42 +20,9 @@ class ConcreteBaseApiRepository extends BaseApiRepository {
     public function getApiRecords($uri, $params = []) { return parent::getApiRecords($uri, $params); }
 }
 
-class BaseApiRepositoryTest extends UnitTestCase
+class BaseApiRepositoryTest extends AbstractApiRepositoryTestCase
 {
-    private $context;
-    /**
-     * @var ApiResponseFixtures
-     */
-    private $fixture;
-    /**
-     * @var ConcreteBaseApiRepository
-     */
-    private $baseApiRepository;
-    /**
-     * @var \Prophecy\Prophecy\ObjectProphecy
-     */
-    private $client;
-
-    public function setUp() {
-        // mock the application context
-        $this->context = $this->prophesize(ApplicationContext::class);
-        $this->context->isProduction()->willReturn(true);
-
-        $this->client = $this->prophesize(Client::class);
-        $this->baseApiRepository = new ConcreteBaseApiRepository($this->client->reveal(), $this->context->reveal());
-
-        $this->fixture = new ApiResponseFixtures();
-    }
-
-    private function injectClientFor($uri) {
-        // mock the Guzzle client
-        $willReturn = $this->fixture->get($uri);
-        $client = $this->prophesize(Client::class);
-        $client->request(BaseApiRepository::HTTP_METHOD, $uri)
-            ->shouldBeCalled()
-            ->willReturn($willReturn);
-        $this->inject($this->baseApiRepository, "client", $client->reveal());
-    }
+    const TESTED_CLASS = 'Opentalent\OtCore\Tests\Unit\Domain\Repository\ConcreteBaseApiRepository';
 
     /**
      * get should build a valid url, send a query and
@@ -71,7 +39,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&itemsPerPage=10&foo=1";
 
         $this->injectClientFor($processed_uri);
-        $actual = $this->baseApiRepository->get($base_uri, $params);
+        $actual = $this->repository->get($base_uri, $params);
 
         $this->assertEquals(200, $actual->getStatusCode());
     }
@@ -91,7 +59,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&itemsPerPage=8";
 
         $this->injectClientFor($processed_uri);
-        $actual = $this->baseApiRepository->get($base_uri, $params);
+        $actual = $this->repository->get($base_uri, $params);
 
         $this->assertEquals(200, $actual->getStatusCode());
     }
@@ -112,10 +80,10 @@ class BaseApiRepositoryTest extends UnitTestCase
         $client->request(BaseApiRepository::HTTP_METHOD, $processed_uri)
             ->shouldBeCalled()
             ->willThrow(new \GuzzleHttp\Exception\TransferException('error'));
-        $this->inject($this->baseApiRepository, "client", $client->reveal());
+        $this->inject($this->repository, "client", $client->reveal());
 
         try {
-            $this->baseApiRepository->get($base_uri, $params);
+            $this->repository->get($base_uri, $params);
             throw new \AssertionError("An ApiRequestException should have been thrown");
         } catch (ApiRequestException $e) {
             $this->assertEquals('error', $e->getMessage());
@@ -136,7 +104,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&itemsPerPage=10&foo=1";
 
         $this->injectClientFor($processed_uri);
-        $actual = $this->baseApiRepository->getBody($base_uri, $params);
+        $actual = $this->repository->getBody($base_uri, $params);
 
         $this->assertEquals('{"@context": "/api/contexts/PortailOrganization"}', $actual);
     }
@@ -155,7 +123,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&itemsPerPage=10&foo=1";
 
         $this->injectClientFor($processed_uri);
-        $actual = $this->baseApiRepository->getJsonDecoded($base_uri, $params);
+        $actual = $this->repository->getJsonDecoded($base_uri, $params);
 
         $this->assertEquals(["@context" => "/api/contexts/PortailOrganization"], $actual);
     }
@@ -172,7 +140,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&filter%5Bwhere%5D%5Bid%5D=1&page=1&totalItems=1&itemsPerPage=8";
         $this->injectClientFor($processed_uri);
 
-        $actual = $this->baseApiRepository->getApiFirstRecord($base_uri, $params);
+        $actual = $this->repository->getApiFirstRecord($base_uri, $params);
 
         $this->assertEquals('PortailOrganization', $actual['@type']);
     }
@@ -189,7 +157,7 @@ class BaseApiRepositoryTest extends UnitTestCase
         $processed_uri = $base_uri . "?_format=json&filter%5Bwhere%5D%5Bid%5D=1&itemsPerPage=8";
         $this->injectClientFor($processed_uri);
 
-        $actual = $this->baseApiRepository->getApiRecords($base_uri, $params);
+        $actual = $this->repository->getApiRecords($base_uri, $params);
 
         $this->assertEquals('PortailOrganization', $actual->getMembers()[0]['@type']);
     }

+ 56 - 0
ot_core/Tests/Unit/Domain/Repository/DonorRepositoryTest.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
+
+use Opentalent\OtCore\Domain\Repository\DonorRepository;
+
+
+class DonorRepositoryTest extends AbstractApiRepositoryTestCase
+{
+    const TESTED_CLASS = "Opentalent\OtCore\Domain\Repository\DonorRepository";
+
+    /**
+     * findByOrganizationId should return an ApiPagedCollection object containing
+     * the donor(s) matching the given organizationId
+     *
+     * @test
+     */
+    public function findByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/donors?_format=json&organizationId=1&page=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findParentsByOrganizationId should return an ApiPagedCollection object containing
+     * the donor(s) of the parent of the given organization
+     *
+     * @test
+     */
+    public function findParentsByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/donors?_format=json&organizationId=1&parent=1&page=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findParentsByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * memberToObject should return null if the given
+     * member has not the good type
+     *
+     * @test
+     */
+    public function memberToObjectError() {
+        $this->assertEquals(
+            null,
+            $this->callMemberToObject(['@type' => 'Invalid'])
+        );
+    }
+}

+ 170 - 0
ot_core/Tests/Unit/Domain/Repository/EventRepositoryTest.php

@@ -0,0 +1,170 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
+
+use Opentalent\OtCore\Domain\Repository\EventRepository;
+
+
+class EventRepositoryTest extends AbstractApiRepositoryTestCase
+{
+    const TESTED_CLASS = "Opentalent\OtCore\Domain\Repository\EventRepository";
+
+    /**
+     * findById should return an Event object matching the given id
+     *
+     * @test
+     */
+    public function findById() {
+        $event_id = 2;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&filter%5Bwhere%5D%5Bid%5D=2&page=1&totalItems=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findById($event_id);
+        $this->assertEquals($event_id, $actual->getId());
+    }
+
+    /**
+     * findByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) matching the given organizationId
+     *
+     * @test
+     */
+    public function findByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) matching the given organizationId
+     *
+     * @test
+     */
+    public function findByOrganizationIdWithParams() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByOrganizationId(
+            $organization_id,
+            new \DateTime('2021-01-01'),
+            new \DateTime('2021-01-31'),
+            $limit=1,
+            $page=1
+        );
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findParentsByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) of the parent of the given organization
+     *
+     * @test
+     */
+    public function findParentsByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&parent=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findParentsByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findParentsByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) of the parent of the given organization
+     *
+     * @test
+     */
+    public function findParentsByOrganizationIdWithParams() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&parent=1";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findParentsByOrganizationId(
+            $organization_id,
+            new \DateTime('2021-01-01'),
+            new \DateTime('2021-01-31'),
+            $limit=1,
+            $page=1
+        );
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findParentsByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) of the parent of the given organization
+     *
+     * @test
+     */
+    public function findChildrenByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&children=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findChildrenByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findParentsByOrganizationId should return an ApiPagedCollection object containing
+     * the event(s) of the parent of the given organization
+     *
+     * @test
+     */
+    public function findChildrenByOrganizationIdWithParams() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&children=1";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findChildrenByOrganizationId(
+            $organization_id,
+            new \DateTime('2021-01-01'),
+            new \DateTime('2021-01-31'),
+            $limit=1,
+            $page=1
+        );
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * searchBy should return an ApiPagedCollection object containing
+     * the event(s) matching the criteria
+     *
+     * @test
+     */
+    public function searchBy() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&filter%5Bwhere%5D%5Bid%5D=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->searchBy($organization_id, ['filter[where][id]' => 1]);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * memberToObject should return null if the given
+     * member has not the good type
+     *
+     * @test
+     */
+    public function memberToObjectError() {
+        $this->assertEquals(
+            null,
+            $this->callMemberToObject(['@type' => 'Invalid'])
+        );
+    }
+
+}

+ 56 - 0
ot_core/Tests/Unit/Domain/Repository/MemberRepositoryTest.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
+
+use Opentalent\OtCore\Domain\Repository\MemberRepository;
+
+
+class MemberRepositoryTest extends AbstractApiRepositoryTestCase
+{
+    const TESTED_CLASS = "Opentalent\OtCore\Domain\Repository\MemberRepository";
+
+    /**
+     * findByOrganizationId should return an ApiPagedCollection object containing
+     * the member(s) matching the given organizationId
+     *
+     * @test
+     */
+    public function findByOrganizationId() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/members?_format=json&filter%5Bwhere%5D%5BorganizationId%5D=1&itemsPerPage=200";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByOrganizationId($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * findByOrganizationId should return an ApiPagedCollection object containing
+     * the member(s) matching the given organizationId
+     *
+     * @test
+     */
+    public function findByOrganizationIdWithCa() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/members_ca?_format=json&filter%5Bwhere%5D%5BorganizationId%5D=1&itemsPerPage=200";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByOrganizationId($organization_id, true);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getOrganizationId());
+    }
+
+    /**
+     * memberToObject should return null if the given
+     * member has not the good type
+     *
+     * @test
+     */
+    public function memberToObjectError() {
+        $this->assertEquals(
+            null,
+            $this->callMemberToObject(['@type' => 'Invalid'])
+        );
+    }
+}

+ 84 - 0
ot_core/Tests/Unit/Domain/Repository/OrganizationRepositoryTest.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace Opentalent\OtCore\Tests\Unit\Domain\Repository;
+
+use Opentalent\OtCore\Domain\Repository\OrganizationRepository;
+
+
+class OrganizationRepositoryTest extends AbstractApiRepositoryTestCase
+{
+    const TESTED_CLASS = "Opentalent\OtCore\Domain\Repository\OrganizationRepository";
+
+    /**
+     * findById should return an the Organization matching the given id
+     *
+     * @test
+     */
+    public function findById() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bid%5D=1&page=1&totalItems=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findById($organization_id);
+        $this->assertEquals($organization_id, $actual->getId());
+    }
+
+    /**
+     * findById should return an the Organization matching the given id
+     *
+     * @test
+     */
+    public function findByName() {
+        $name = 'a name';
+
+        $expected_uri = "https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bname%5D=a+name&page=1&totalItems=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByName($name);
+        $this->assertEquals(1, $actual->getId());
+    }
+
+    /**
+     * findById should return an the Organization matching the given id
+     *
+     * @test
+     */
+    public function findByInexistantName() {
+        $name = 'a unknown name';
+
+        $expected_uri = "https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bname%5D=a+unknown+name&page=1&totalItems=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findByName($name);
+        $this->assertEquals(1, $actual->getId());
+    }
+
+    /**
+     * findById should return an the Organization matching the given id
+     *
+     * @test
+     */
+    public function findChildrenById() {
+        $organization_id = 1;
+
+        $expected_uri = "https://api.opentalent.fr/api/public/organizations?_format=json&parentId=1&children=1&page=1&itemsPerPage=8";
+        $this->injectClientFor($expected_uri);
+
+        $actual = $this->repository->findChildrenById($organization_id);
+        $this->assertEquals($organization_id, $actual->getMembers()[0]->getId());
+    }
+
+    /**
+     * memberToObject should return null if the given
+     * member has not the good type
+     *
+     * @test
+     */
+    public function memberToObjectError() {
+        $this->assertEquals(
+            null,
+            $this->callMemberToObject(['@type' => 'Invalid'])
+        );
+    }
+}

+ 84 - 7
ot_core/Tests/Unit/Fixtures/ApiResponseFixtures.php

@@ -5,14 +5,18 @@ namespace Opentalent\OtCore\Tests\Unit\Fixtures;
 
 
 use TYPO3\CMS\Core\Http\HtmlResponse;
-use TYPO3\CMS\Core\Http\JsonResponse;
-use TYPO3\CMS\Core\Http\Response;
 
+
+/**
+ * This class return responses that mime the Opentalent API
+ *
+ * @package Opentalent\OtCore\Tests\Unit\Fixtures
+ */
 class ApiResponseFixtures
 {
     private $responses = [
         'stub' => '{"@context": "/api/contexts/PortailOrganization"}',
-        'org-1' => '
+        'org' => '
         {
             "@context": "/api/contexts/PortailOrganization",
             "@id": "/api/public/organizations?_format=json&filter[where][id]=1",
@@ -45,7 +49,7 @@ class ApiResponseFixtures
                 }],
         "hydra:search": {}
         }',
-        'event-2' => '
+        'event' => '
         {
             "@context": "/api/contexts/PortailEvent",
             "@id": "/api/public/events?_format=json&filter[where][id]=2",
@@ -93,15 +97,88 @@ class ApiResponseFixtures
                 }
         ],
         "hydra:search":{}
+        }',
+        'donor' => '
+        {
+            "@context": "/api/contexts/PortailDonor",
+            "@id": "/api/public/donors?_format=json&organizationId=1",
+            "@type": "hydra:PagedCollection",
+            "hydra:totalItems": 1,
+            "hydra:itemsPerPage": 30,
+            "hydra:firstPage": "/api/public/donors?_format=json&organizationId=1",
+            "hydra:lastPage": "/api/public/donors?_format=json&organizationId=1",
+            "hydra:member": [
+                {
+                    "@id": "/api/public/donors/3",
+                    "@type": "PortailDonor",
+                    "organizationId": 1,
+                    "name": "Donor",
+                    "email": "email@domain.com",
+                    "telphone": "0000000000",
+                    "website": "www.website.com",
+                    "wording": null,
+                    "displayedOn": "NONE",
+                    "logo": "https://api.opentalent.fr/_internal/secure/files/1"
+                }
+            ],
+            "hydra:search": {}
+        }',
+        'member' => '
+        {
+            "@context": "/api/contexts/PortailMemberBySpeciality",
+            "@id": "/api/public/members?_format=json&filter[where][id]=4",
+            "@type": "hydra:PagedCollection",
+            "hydra:totalItems": 1,
+            "hydra:itemsPerPage": 30,
+            "hydra:firstPage": "/api/public/members?_format=json&filter%5Bwhere%5D%5Bid%5D=4",
+            "hydra:lastPage": "/api/public/members?_format=json&filter%5Bwhere%5D%5Bid%5D=4",
+            "hydra:member": [
+                {
+                    "@id": "/api/public/members/5",
+                    "@type": "PortailMemberBySpeciality",
+                    "organizationId": 1,
+                    "gender": "MISS",
+                    "givenName": "Marie-Aiglantine",
+                    "name": "De Saint-Marcellin",
+                    "startDate": "2010-01-01T00:00:00+00:00",
+                    "endDate": null,
+                    "instrumentGroup": "OBOE",
+                    "instrument": "OBOE",
+                    "personId": 4,
+                    "image": "https://api.opentalent.fr/_internal/secure/files/1"
+                }
+            ],
+            "hydra:search": {}
         }'
     ];
 
+    /**
+     * Do the mapping between URI and responses
+     * /!\ Each of these uri shall be tested against the Opentalent API. Without
+     *     this, those tests won't prove anything...
+     *
+     * @var string[]
+     */
     private $map = [
         'https://api.opentalent.fr/api/public/organizations?_format=json&itemsPerPage=10&foo=1' => 'stub',
         'https://api.opentalent.fr/api/public/organizations?_format=json&itemsPerPage=8' => 'stub',
-        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bid%5D=1&page=1&totalItems=1&itemsPerPage=8' => 'org-1',
-        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bid%5D=1&itemsPerPage=8' => 'org-1',
-        'https://api.opentalent.fr/api/public/events?_format=json&itemsPerPage=8&filter[where][id]=2' => 'event-2'
+        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bid%5D=1&page=1&totalItems=1&itemsPerPage=8' => 'org',
+        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bname%5D=a+name&page=1&totalItems=1&itemsPerPage=8' => 'org',
+        'https://api.opentalent.fr/api/public/organizations?_format=json&parentId=1&children=1&page=1&itemsPerPage=8' => 'org',
+        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bid%5D=1&itemsPerPage=8' => 'org',
+        'https://api.opentalent.fr/api/public/organizations?_format=json&filter%5Bwhere%5D%5Bname%5D=a+unknown+name&page=1&totalItems=1&itemsPerPage=8' => 'org',
+        'https://api.opentalent.fr/api/public/events?_format=json&filter%5Bwhere%5D%5Bid%5D=2&page=1&totalItems=1&itemsPerPage=8' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&itemsPerPage=8' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&parent=1&itemsPerPage=8' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&children=1&itemsPerPage=8' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&filter%5Bwhere%5D%5Bid%5D=1&itemsPerPage=8' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&page=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&parent=1' => 'event',
+        'https://api.opentalent.fr/api/public/events?_format=json&organizationId=1&itemsPerPage=1&filter%5Bwhere%5D%5BdatetimeStart%5D%5Bgte%5D=2021-01-01T00%3A00%3A00%2B00%3A00&filter%5Bwhere%5D%5BdatetimeEnd%5D%5Blte%5D=2021-01-31T00%3A00%3A00%2B00%3A00&filter%5Border%5D%5B0%5D%5BdatetimeStart%5D=ASC&children=1' => 'event',
+        'https://api.opentalent.fr/api/public/donors?_format=json&organizationId=1&page=1&itemsPerPage=8' => 'donor',
+        'https://api.opentalent.fr/api/public/donors?_format=json&organizationId=1&parent=1&page=1&itemsPerPage=8' => 'donor',
+        'https://api.opentalent.fr/api/public/members?_format=json&filter%5Bwhere%5D%5BorganizationId%5D=1&itemsPerPage=200' => 'member',
+        'https://api.opentalent.fr/api/public/members_ca?_format=json&filter%5Bwhere%5D%5BorganizationId%5D=1&itemsPerPage=200' => 'member'
     ];
 
     public function get($url) {