buckets/tests/Doctrine/ScenarioOwnerExtensionTest.php

86 lines
2.9 KiB
PHP

<?php
namespace App\Tests\Doctrine;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
use App\Doctrine\ScenarioOwnerExtension;
use App\Entity\Scenario;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\MockObject\Stub;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Bundle\SecurityBundle\Security;
/**
* Unit-covers the AbstractOwnerScopeExtension base via its simplest concrete
* subclass (Scenario owns the `owner` column directly). The HTTP-level
* functional tests always run authenticated against their own resource, so the
* base's two early-return guards (wrong resource class, anonymous user) are only
* reachable here in isolation.
*/
final class ScenarioOwnerExtensionTest extends KernelTestCase
{
private function queryBuilder(): \Doctrine\ORM\QueryBuilder
{
self::bootKernel();
/** @var EntityManagerInterface $em */
$em = self::getContainer()->get(EntityManagerInterface::class);
return $em->createQueryBuilder()
->select('s')
->from(Scenario::class, 's');
}
private function extensionWithUser(?object $user): ScenarioOwnerExtension
{
/** @var Security&Stub $security */
$security = $this->createStub(Security::class);
$security->method('getUser')->willReturn($user);
return new ScenarioOwnerExtension($security);
}
public function testAddsOwnerFilterForAnAuthenticatedUserOnItsOwnResource(): void
{
$qb = $this->queryBuilder();
$extension = $this->extensionWithUser(new User());
$extension->applyToCollection($qb, new QueryNameGenerator(), Scenario::class);
self::assertStringContainsStringIgnoringCase(
'.owner = :',
(string) $qb->getDQL(),
'An authenticated read of its own resource must be scoped to the owner.',
);
}
public function testDoesNothingForAResourceItDoesNotGuard(): void
{
$qb = $this->queryBuilder();
$extension = $this->extensionWithUser(new User());
// Bucket is guarded by a different extension — this one must no-op.
$extension->applyToCollection($qb, new QueryNameGenerator(), \App\Entity\Bucket::class);
self::assertStringNotContainsString(
'owner',
(string) $qb->getDQL(),
'The extension must not touch queries for a resource it does not guard.',
);
}
public function testDoesNothingForAnAnonymousRequest(): void
{
$qb = $this->queryBuilder();
$extension = $this->extensionWithUser(null);
$extension->applyToItem($qb, new QueryNameGenerator(), Scenario::class, ['id' => 'x']);
self::assertStringNotContainsString(
'owner',
(string) $qb->getDQL(),
'With no authenticated user the extension must not add an owner filter '
.'(it is a fail-safe behind the resource-level ROLE_USER wall).',
);
}
}