From a1933386648246d90e85d28db301b65027113cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Gangloff?= Date: Wed, 15 Oct 2025 18:55:39 +0200 Subject: [PATCH] test: add WatchlistUpdateProcessor tests --- .env.test | 6 ++ src/Entity/WatchList.php | 10 +-- src/State/WatchListUpdateProcessor.php | 2 +- tests/Controller/WatchlistControllerTest.php | 37 ++-------- tests/State/WatchListUpdateProcessorTest.php | 74 ++++++++++++++++++++ 5 files changed, 92 insertions(+), 37 deletions(-) create mode 100644 tests/State/WatchListUpdateProcessorTest.php diff --git a/.env.test b/.env.test index 4743668..0a8ac7b 100644 --- a/.env.test +++ b/.env.test @@ -3,3 +3,9 @@ KERNEL_CLASS='App\Kernel' APP_SECRET='$ecretf0rt3st' SYMFONY_DEPRECATIONS_HELPER=999999 DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:5432/postgres?serverVersion=16&charset=utf8" + +# FEATURES +LIMITED_FEATURES=true +LIMIT_MAX_WATCHLIST=10 +LIMIT_MAX_WATCHLIST_DOMAINS=10 +LIMIT_MAX_WATCHLIST_WEBHOOKS=10 diff --git a/src/Entity/WatchList.php b/src/Entity/WatchList.php index b3f3980..e88ced9 100644 --- a/src/Entity/WatchList.php +++ b/src/Entity/WatchList.php @@ -90,7 +90,7 @@ use Symfony\Component\Uid\Uuid; ), new Put( normalizationContext: ['groups' => 'watchlist:item'], - denormalizationContext: ['groups' => ['watchlist:create', 'watchlist:token']], + denormalizationContext: ['groups' => ['watchlist:update']], security: 'object.user == user', processor: WatchListUpdateProcessor::class, ), @@ -163,7 +163,7 @@ class WatchList #[ORM\JoinTable(name: 'watch_lists_domains', joinColumns: [new ORM\JoinColumn(name: 'watch_list_token', referencedColumnName: 'token', onDelete: 'CASCADE')], inverseJoinColumns: [new ORM\JoinColumn(name: 'domain_ldh_name', referencedColumnName: 'ldh_name', onDelete: 'CASCADE')])] - #[Groups(['watchlist:create', 'watchlist:list', 'watchlist:item'])] + #[Groups(['watchlist:create', 'watchlist:list', 'watchlist:item', 'watchlist:update'])] private Collection $domains; /** @@ -175,11 +175,11 @@ class WatchList private Collection $watchListTriggers; #[ORM\ManyToOne(inversedBy: 'watchLists')] - #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create'])] + #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create', 'watchlist:update'])] private ?Connector $connector = null; #[ORM\Column(length: 255, nullable: true)] - #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create'])] + #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create', 'watchlist:update'])] private ?string $name = null; #[ORM\Column] @@ -188,7 +188,7 @@ class WatchList #[SerializedName('dsn')] #[ORM\Column(type: Types::SIMPLE_ARRAY, nullable: true)] - #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create'])] + #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create', 'watchlist:update'])] private ?array $webhookDsn = null; public function __construct() diff --git a/src/State/WatchListUpdateProcessor.php b/src/State/WatchListUpdateProcessor.php index 79ee9b8..056abd9 100644 --- a/src/State/WatchListUpdateProcessor.php +++ b/src/State/WatchListUpdateProcessor.php @@ -45,7 +45,7 @@ readonly class WatchListUpdateProcessor implements ProcessorInterface { /** @var User $user */ $user = $this->security->getUser(); - $data->setUser($user); + $data->setUser($user)->setToken($uriVariables['token'] ?? $data->getToken()); if ($this->parameterBag->get('limited_features')) { if ($data->getDomains()->count() > (int) $this->parameterBag->get('limit_max_watchlist_domains')) { diff --git a/tests/Controller/WatchlistControllerTest.php b/tests/Controller/WatchlistControllerTest.php index 5a81435..938cad3 100644 --- a/tests/Controller/WatchlistControllerTest.php +++ b/tests/Controller/WatchlistControllerTest.php @@ -3,11 +3,10 @@ namespace App\Tests\Controller; use ApiPlatform\Symfony\Bundle\Test\ApiTestCase; -use ApiPlatform\Symfony\Bundle\Test\Client; use App\Entity\WatchList; -use App\Factory\UserFactory; use App\Tests\AuthenticatedUserTrait; use App\Tests\Service\RDAPServiceTest; +use App\Tests\State\WatchListUpdateProcessorTest; use PHPUnit\Framework\Attributes\DependsExternal; use Zenstruck\Foundry\Test\Factories; @@ -19,7 +18,7 @@ final class WatchlistControllerTest extends ApiTestCase #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] public function testGetWatchlistCollection(): void { - $client = $this->createUserAndWatchlist(); + $client = WatchListUpdateProcessorTest::createUserAndWatchlist(); $response = $client->request('GET', '/api/watchlists'); @@ -31,20 +30,13 @@ final class WatchlistControllerTest extends ApiTestCase $this->assertCount(1, $data['hydra:member']); } - #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] - public function testCreateWatchlist(): void - { - $this->createUserAndWatchlist(); - $this->assertResponseIsSuccessful(); - $this->assertResponseStatusCodeSame(201); - $this->assertMatchesResourceItemJsonSchema(WatchList::class); - } - #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] public function testGetTrackedDomains() { - $client = $this->createUserAndWatchlist(); + $client = WatchListUpdateProcessorTest::createUserAndWatchlist(); + $client->getContainer()->get('doctrine')->getManager()->clear(); + sleep(2); $response = $client->request('GET', '/api/tracked'); $this->assertResponseIsSuccessful(); @@ -56,7 +48,7 @@ final class WatchlistControllerTest extends ApiTestCase #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] public function testGetWatchlistFeeds() { - $client = $this->createUserAndWatchlist(); + $client = WatchListUpdateProcessorTest::createUserAndWatchlist(); $response = $client->request('GET', '/api/watchlists'); $token = $response->toArray()['hydra:member'][0]['token']; @@ -73,21 +65,4 @@ final class WatchlistControllerTest extends ApiTestCase $this->assertResponseIsSuccessful(); $this->assertResponseHeaderSame('content-type', 'application/atom+xml; charset=utf-8'); } - - private function createUserAndWatchlist(): Client - { - $client = self::createClientWithCredentials(self::getToken(UserFactory::createOne())); - $client->request('POST', '/api/watchlists', ['json' => [ - 'domains' => ['/api/domains/iana.org'], - 'name' => 'My Watchlist', - 'triggers' => [ - ['action' => 'email', 'event' => 'last changed'], - ['action' => 'email', 'event' => 'transfer'], - ['action' => 'email', 'event' => 'expiration'], - ['action' => 'email', 'event' => 'deletion'], - ], - ]]); - - return $client; - } } diff --git a/tests/State/WatchListUpdateProcessorTest.php b/tests/State/WatchListUpdateProcessorTest.php new file mode 100644 index 0000000..5e03fb1 --- /dev/null +++ b/tests/State/WatchListUpdateProcessorTest.php @@ -0,0 +1,74 @@ +assertResponseIsSuccessful(); + $this->assertResponseStatusCodeSame(201); + $this->assertMatchesResourceItemJsonSchema(WatchList::class); + } + + #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] + public function testCreateTwoWatchlistWithSameDomains(): void + { + $client = self::createClientWithCredentials(self::getToken(UserFactory::createOne())); + self::createUserAndWatchlist($client); + self::createUserAndWatchlist($client); + $this->assertResponseStatusCodeSame(403); + } + + #[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')] + public function testUpdateWatchlist(): void + { + $client = self::createUserAndWatchlist(); + $response = $client->request('GET', '/api/watchlists'); + $token = $response->toArray()['hydra:member'][0]['token']; + + $response = $client->request('PUT', '/api/watchlists/'.$token, ['json' => [ + 'domains' => ['/api/domains/iana.org', '/api/domains/example.com'], + 'name' => 'My modified Watchlist', + 'triggers' => [ + ['action' => 'email', 'event' => 'last changed'], + ], + ]]); + $this->assertResponseIsSuccessful(); + $this->assertMatchesResourceItemJsonSchema(WatchList::class); + $data = $response->toArray(); + $this->assertCount(2, $data['domains']); + $this->assertCount(1, $data['triggers']); + } + + public static function createUserAndWatchlist(?Client $client = null): Client + { + $client = $client ?? self::createClientWithCredentials(self::getToken(UserFactory::createOne())); + $client->request('POST', '/api/watchlists', ['json' => [ + 'domains' => ['/api/domains/example.com'], + 'name' => 'My Watchlist', + 'triggers' => [ + ['action' => 'email', 'event' => 'last changed'], + ['action' => 'email', 'event' => 'transfer'], + ['action' => 'email', 'event' => 'expiration'], + ['action' => 'email', 'event' => 'deletion'], + ], + ]]); + + return $client; + } +}