Extrait l'helper authenticatedClient(), $alwaysBootKernel et getEm() dans une classe de base commune aux tests fonctionnels API Platform du module Core. Supprime la duplication entre PermissionApiTest et RoleApiTest (flaggee en code review de la Task 2). Prepare le terrain pour le nouveau UserRbacApiTest introduit avec la Task 4.
182 lines
6.6 KiB
PHP
182 lines
6.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Module\Core\Api;
|
|
|
|
use App\Module\Core\Domain\Entity\Permission;
|
|
|
|
/**
|
|
* Tests fonctionnels de l'exposition API Platform de l'entite Permission.
|
|
*
|
|
* Strategie de donnees : on cree directement quelques instances de Permission
|
|
* via l'EntityManager au setUp (choix le plus simple et le plus rapide, pas
|
|
* besoin de booter la commande app:sync-permissions). Les fixtures de test
|
|
* sont prefixees par "test." pour ne pas collisionner avec d'eventuelles
|
|
* permissions reelles et sont nettoyees en tearDown.
|
|
*
|
|
* @internal
|
|
*/
|
|
final class PermissionApiTest extends AbstractApiTestCase
|
|
{
|
|
private const TEST_CODE_PREFIX = 'test.';
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// On boote le kernel une fois pour pouvoir seeder les fixtures.
|
|
// ATTENTION : ne pas stocker l'EntityManager dans une propriete,
|
|
// chaque createClient() dans les tests rebootera le kernel et
|
|
// invalidera tout EM capture ici (cf. $alwaysBootKernel = true).
|
|
self::bootKernel();
|
|
$em = $this->getEm();
|
|
|
|
// Nettoyage defensif au cas ou un run precedent aurait laisse des restes.
|
|
$this->cleanupTestPermissions();
|
|
|
|
// Donnees de test : deux permissions "core" dont une orpheline,
|
|
// plus une permission d'un autre module pour verifier le filtre.
|
|
$p1 = new Permission('test.core.users.view', 'View users (test)', 'core');
|
|
$p2 = new Permission('test.core.users.manage', 'Manage users (test)', 'core');
|
|
$p3 = new Permission('test.commercial.clients.view', 'View clients (test)', 'commercial');
|
|
$p2->markOrphan();
|
|
|
|
$em->persist($p1);
|
|
$em->persist($p2);
|
|
$em->persist($p3);
|
|
$em->flush();
|
|
$em->clear();
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->cleanupTestPermissions();
|
|
parent::tearDown();
|
|
}
|
|
|
|
public function testGetCollectionAsAdminReturns200(): void
|
|
{
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$response = $client->request('GET', '/api/permissions');
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = $response->toArray();
|
|
// API Platform 4 emet du JSON-LD 1.1 avec un @context qui utilise un
|
|
// @vocab : les cles sortent donc non prefixees (`member`, `totalItems`)
|
|
// au lieu des anciennes `hydra:member` / `hydra:totalItems`.
|
|
self::assertArrayHasKey('member', $data);
|
|
self::assertGreaterThanOrEqual(3, $data['totalItems']);
|
|
}
|
|
|
|
public function testCollectionFilterByModule(): void
|
|
{
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$response = $client->request('GET', '/api/permissions', [
|
|
'query' => ['module' => 'core'],
|
|
]);
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = $response->toArray();
|
|
foreach ($data['member'] as $item) {
|
|
self::assertSame('core', $item['module']);
|
|
}
|
|
// Doit contenir au moins nos deux permissions core de test.
|
|
$codes = array_column($data['member'], 'code');
|
|
self::assertContains('test.core.users.view', $codes);
|
|
self::assertContains('test.core.users.manage', $codes);
|
|
self::assertNotContains('test.commercial.clients.view', $codes);
|
|
}
|
|
|
|
public function testCollectionFilterByOrphanTrue(): void
|
|
{
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$response = $client->request('GET', '/api/permissions', [
|
|
'query' => ['orphan' => 'true'],
|
|
]);
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = $response->toArray();
|
|
foreach ($data['member'] as $item) {
|
|
self::assertTrue($item['orphan']);
|
|
}
|
|
$codes = array_column($data['member'], 'code');
|
|
// La permission marquee orpheline dans setUp() doit remonter...
|
|
self::assertContains('test.core.users.manage', $codes);
|
|
// ...et celles non orphelines doivent etre exclues.
|
|
self::assertNotContains('test.core.users.view', $codes);
|
|
self::assertNotContains('test.commercial.clients.view', $codes);
|
|
}
|
|
|
|
public function testCollectionFilterByOrphanFalse(): void
|
|
{
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$response = $client->request('GET', '/api/permissions', [
|
|
'query' => ['orphan' => 'false'],
|
|
]);
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = $response->toArray();
|
|
foreach ($data['member'] as $item) {
|
|
self::assertFalse($item['orphan']);
|
|
}
|
|
$codes = array_column($data['member'], 'code');
|
|
self::assertContains('test.core.users.view', $codes);
|
|
self::assertNotContains('test.core.users.manage', $codes);
|
|
}
|
|
|
|
public function testGetItemAsAdminReturnsAllReadFields(): void
|
|
{
|
|
/** @var null|Permission $permission */
|
|
$permission = $this->getEm()->getRepository(Permission::class)
|
|
->findOneBy(['code' => 'test.core.users.view'])
|
|
;
|
|
self::assertNotNull($permission);
|
|
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$response = $client->request('GET', '/api/permissions/'.$permission->getId());
|
|
|
|
self::assertResponseIsSuccessful();
|
|
$data = $response->toArray();
|
|
self::assertSame($permission->getId(), $data['id']);
|
|
self::assertSame('test.core.users.view', $data['code']);
|
|
self::assertSame('View users (test)', $data['label']);
|
|
self::assertSame('core', $data['module']);
|
|
self::assertFalse($data['orphan']);
|
|
}
|
|
|
|
public function testPostIsMethodNotAllowed(): void
|
|
{
|
|
$client = $this->authenticatedClient('admin', 'admin');
|
|
$client->request('POST', '/api/permissions', [
|
|
'headers' => ['Content-Type' => 'application/ld+json'],
|
|
'json' => ['code' => 'test.foo.bar.baz', 'label' => 'Foo', 'module' => 'foo'],
|
|
]);
|
|
|
|
self::assertResponseStatusCodeSame(405);
|
|
}
|
|
|
|
public function testUnauthenticatedReturns401(): void
|
|
{
|
|
$client = self::createClient();
|
|
$client->request('GET', '/api/permissions');
|
|
|
|
self::assertResponseStatusCodeSame(401);
|
|
}
|
|
|
|
public function testNonAdminReturns403(): void
|
|
{
|
|
$client = $this->authenticatedClient('alice', 'alice');
|
|
$client->request('GET', '/api/permissions');
|
|
|
|
self::assertResponseStatusCodeSame(403);
|
|
}
|
|
|
|
private function cleanupTestPermissions(): void
|
|
{
|
|
$this->getEm()->createQuery(
|
|
'DELETE FROM '.Permission::class.' p WHERE p.code LIKE :prefix'
|
|
)->setParameter('prefix', self::TEST_CODE_PREFIX.'%')->execute();
|
|
}
|
|
}
|