mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
test: add some KernelTestCase
This commit is contained in:
@@ -21,6 +21,7 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
|||||||
use Symfony\Component\RateLimiter\RateLimiterFactory;
|
use Symfony\Component\RateLimiter\RateLimiterFactory;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use Symfony\Component\Serializer\SerializerInterface;
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
|
|
||||||
class RegistrationController extends AbstractController
|
class RegistrationController extends AbstractController
|
||||||
{
|
{
|
||||||
@@ -33,6 +34,7 @@ class RegistrationController extends AbstractController
|
|||||||
private readonly SerializerInterface $serializer,
|
private readonly SerializerInterface $serializer,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
private readonly KernelInterface $kernel,
|
private readonly KernelInterface $kernel,
|
||||||
|
private readonly ValidatorInterface $validator,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,14 +66,16 @@ class RegistrationController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->serializer->deserialize($request->getContent(), User::class, 'json', ['groups' => 'user:register']);
|
$user = $this->serializer->deserialize($request->getContent(), User::class, 'json', ['groups' => 'user:register']);
|
||||||
if (null === $user->getEmail() || null === $user->getPassword()) {
|
$violations = $this->validator->validate($user);
|
||||||
throw new BadRequestHttpException('Bad request');
|
|
||||||
|
if ($violations->count() > 0) {
|
||||||
|
throw new BadRequestHttpException($violations->get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->setPassword(
|
$user->setPassword(
|
||||||
$userPasswordHasher->hashPassword(
|
$userPasswordHasher->hashPassword(
|
||||||
$user,
|
$user,
|
||||||
$user->getPassword()
|
$user->getPlainPassword()
|
||||||
)
|
)
|
||||||
)->setCreatedAt(new \DateTimeImmutable());
|
)->setCreatedAt(new \DateTimeImmutable());
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\ApiProperty;
|
||||||
use ApiPlatform\Metadata\ApiResource;
|
use ApiPlatform\Metadata\ApiResource;
|
||||||
use ApiPlatform\Metadata\Get;
|
use ApiPlatform\Metadata\Get;
|
||||||
use App\Config\EventAction;
|
use App\Config\EventAction;
|
||||||
@@ -75,6 +76,11 @@ class Domain
|
|||||||
*/
|
*/
|
||||||
#[ORM\OneToMany(targetEntity: DomainEvent::class, mappedBy: 'domain', cascade: ['persist'], orphanRemoval: true)]
|
#[ORM\OneToMany(targetEntity: DomainEvent::class, mappedBy: 'domain', cascade: ['persist'], orphanRemoval: true)]
|
||||||
#[Groups(['domain:item', 'domain:list', 'watchlist:list'])]
|
#[Groups(['domain:item', 'domain:list', 'watchlist:list'])]
|
||||||
|
#[ApiProperty(
|
||||||
|
openapiContext: [
|
||||||
|
'type' => 'array',
|
||||||
|
]
|
||||||
|
)]
|
||||||
private Collection $events;
|
private Collection $events;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\ApiProperty;
|
||||||
use ApiPlatform\Metadata\ApiResource;
|
use ApiPlatform\Metadata\ApiResource;
|
||||||
use App\Repository\EntityRepository;
|
use App\Repository\EntityRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
@@ -77,7 +78,13 @@ class Entity
|
|||||||
#[Groups(['entity:item', 'domain:item'])]
|
#[Groups(['entity:item', 'domain:item'])]
|
||||||
private Collection $events;
|
private Collection $events;
|
||||||
|
|
||||||
#[ORM\Column]
|
#[ORM\Column(type: 'json')]
|
||||||
|
#[ApiProperty(
|
||||||
|
openapiContext: [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => ['type' => 'array'],
|
||||||
|
]
|
||||||
|
)]
|
||||||
#[Groups(['entity:item', 'domain:item'])]
|
#[Groups(['entity:item', 'domain:item'])]
|
||||||
private array $jCard = [];
|
private array $jCard = [];
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
|
|||||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
use Symfony\Component\Serializer\Attribute\Groups;
|
use Symfony\Component\Serializer\Attribute\Groups;
|
||||||
|
use Symfony\Component\Serializer\Attribute\SerializedName;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||||
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])]
|
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_EMAIL', fields: ['email'])]
|
||||||
@@ -46,6 +48,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
|
|
||||||
#[ORM\Column(length: 180)]
|
#[ORM\Column(length: 180)]
|
||||||
#[Groups(['user:list', 'user:register'])]
|
#[Groups(['user:list', 'user:register'])]
|
||||||
|
#[Assert\Email]
|
||||||
|
#[Assert\NotBlank]
|
||||||
private ?string $email = null;
|
private ?string $email = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +63,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
* @var string|null The hashed password
|
* @var string|null The hashed password
|
||||||
*/
|
*/
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
#[Groups(['user:register'])]
|
|
||||||
private ?string $password = null;
|
private ?string $password = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,6 +83,10 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
private ?\DateTimeImmutable $verifiedAt = null;
|
private ?\DateTimeImmutable $verifiedAt = null;
|
||||||
|
|
||||||
|
#[Assert\PasswordStrength]
|
||||||
|
#[Assert\NotBlank]
|
||||||
|
#[SerializedName('password')]
|
||||||
|
#[Groups(['user:register'])]
|
||||||
private ?string $plainPassword = null;
|
private ?string $plainPassword = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ final class UserFactory extends PersistentObjectFactory
|
|||||||
protected function defaults(): array|callable
|
protected function defaults(): array|callable
|
||||||
{
|
{
|
||||||
$createdAt = \DateTimeImmutable::createFromMutable(self::faker()->dateTime());
|
$createdAt = \DateTimeImmutable::createFromMutable(self::faker()->dateTime());
|
||||||
$plainPassword = self::faker()->password(8, 20);
|
$plainPassword = self::faker()->password(16, 20);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'createdAt' => $createdAt,
|
'createdAt' => $createdAt,
|
||||||
|
|||||||
27
tests/Controller/ConnectorControllerTest.php
Normal file
27
tests/Controller/ConnectorControllerTest.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Connector;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use App\Tests\AbstractTest;
|
||||||
|
use Zenstruck\Foundry\Test\Factories;
|
||||||
|
use Zenstruck\Foundry\Test\ResetDatabase;
|
||||||
|
|
||||||
|
final class ConnectorControllerTest extends AbstractTest
|
||||||
|
{
|
||||||
|
use ResetDatabase;
|
||||||
|
use Factories;
|
||||||
|
|
||||||
|
public function testGetConnectorCollection(): void
|
||||||
|
{
|
||||||
|
$testUser = UserFactory::createOne();
|
||||||
|
$client = ConnectorControllerTest::createClientWithCredentials(ConnectorControllerTest::getToken($testUser));
|
||||||
|
|
||||||
|
$response = $client->request('GET', '/api/connectors');
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertMatchesResourceCollectionJsonSchema(Connector::class);
|
||||||
|
$this->assertCount(0, $response->toArray()['hydra:member']);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
tests/Controller/DomainRefreshControllerTest.php
Normal file
26
tests/Controller/DomainRefreshControllerTest.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
use App\Entity\Domain;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use App\Tests\AbstractTest;
|
||||||
|
use App\Tests\Service\RDAPServiceTest;
|
||||||
|
use PHPUnit\Framework\Attributes\DependsExternal;
|
||||||
|
use Zenstruck\Foundry\Test\Factories;
|
||||||
|
|
||||||
|
final class DomainRefreshControllerTest extends AbstractTest
|
||||||
|
{
|
||||||
|
use Factories;
|
||||||
|
|
||||||
|
#[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')]
|
||||||
|
public function testRegisterDomain(): void
|
||||||
|
{
|
||||||
|
$testUser = UserFactory::createOne();
|
||||||
|
$client = DomainRefreshControllerTest::createClientWithCredentials(DomainRefreshControllerTest::getToken($testUser));
|
||||||
|
$client->request('GET', '/api/domains/example.com');
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertMatchesResourceItemJsonSchema(Domain::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Tests;
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
use App\Factory\UserFactory;
|
use App\Factory\UserFactory;
|
||||||
|
use App\Tests\AbstractTest;
|
||||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
use Zenstruck\Foundry\Test\Factories;
|
use Zenstruck\Foundry\Test\Factories;
|
||||||
use Zenstruck\Foundry\Test\ResetDatabase;
|
use Zenstruck\Foundry\Test\ResetDatabase;
|
||||||
|
|
||||||
final class UserTest extends AbstractTest
|
final class MeControllerTest extends AbstractTest
|
||||||
{
|
{
|
||||||
use ResetDatabase;
|
use ResetDatabase;
|
||||||
use Factories;
|
use Factories;
|
||||||
@@ -19,9 +20,8 @@ final class UserTest extends AbstractTest
|
|||||||
public function testGetMyProfile(): void
|
public function testGetMyProfile(): void
|
||||||
{
|
{
|
||||||
$testUser = UserFactory::createOne();
|
$testUser = UserFactory::createOne();
|
||||||
$client = UserTest::createClientWithCredentials(UserTest::getToken($testUser));
|
$client = MeControllerTest::createClientWithCredentials(MeControllerTest::getToken($testUser));
|
||||||
|
|
||||||
$client->loginUser($testUser);
|
|
||||||
$client->request('GET', '/api/me');
|
$client->request('GET', '/api/me');
|
||||||
|
|
||||||
$this->assertResponseIsSuccessful();
|
$this->assertResponseIsSuccessful();
|
||||||
78
tests/Controller/RegistrationControllerTest.php
Normal file
78
tests/Controller/RegistrationControllerTest.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
use Zenstruck\Foundry\Test\Factories;
|
||||||
|
use Zenstruck\Foundry\Test\ResetDatabase;
|
||||||
|
|
||||||
|
final class RegistrationControllerTest extends ApiTestCase
|
||||||
|
{
|
||||||
|
use ResetDatabase;
|
||||||
|
use Factories;
|
||||||
|
|
||||||
|
protected static ContainerInterface $container;
|
||||||
|
protected static EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
RegistrationControllerTest::$container = RegistrationControllerTest::getContainer();
|
||||||
|
RegistrationControllerTest::$entityManager = RegistrationControllerTest::$container->get(EntityManagerInterface::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegister(): void
|
||||||
|
{
|
||||||
|
$testUser = UserFactory::createOne();
|
||||||
|
RegistrationControllerTest::$entityManager->remove($testUser);
|
||||||
|
RegistrationControllerTest::$entityManager->flush();
|
||||||
|
|
||||||
|
$client = $this->createClient();
|
||||||
|
$client->request('POST', '/api/register', [
|
||||||
|
'json' => [
|
||||||
|
'email' => $testUser->getEmail(),
|
||||||
|
'password' => $testUser->getPlainPassword(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertResponseStatusCodeSame(201);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterEmptyEmail(): void
|
||||||
|
{
|
||||||
|
$client = $this->createClient();
|
||||||
|
$client->request('POST', '/api/register', [
|
||||||
|
'json' => [
|
||||||
|
'email' => '',
|
||||||
|
'password' => 'MySuperPassword123',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertResponseStatusCodeSame(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterEmptyPassword(): void
|
||||||
|
{
|
||||||
|
$client = $this->createClient();
|
||||||
|
$client->request('POST', '/api/register', [
|
||||||
|
'json' => [
|
||||||
|
'email' => 'test@domainwatchdog.eu',
|
||||||
|
'password' => '',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertResponseStatusCodeSame(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegisterWeakPassword(): void
|
||||||
|
{
|
||||||
|
$client = $this->createClient();
|
||||||
|
$client->request('POST', '/api/register', [
|
||||||
|
'json' => [
|
||||||
|
'email' => 'test@domainwatchdog.eu',
|
||||||
|
'password' => '123',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$this->assertResponseStatusCodeSame(400);
|
||||||
|
}
|
||||||
|
}
|
||||||
90
tests/Controller/WatchlistControllerTest.php
Normal file
90
tests/Controller/WatchlistControllerTest.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
|
use ApiPlatform\Symfony\Bundle\Test\Client;
|
||||||
|
use App\Entity\WatchList;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use App\Tests\AbstractTest;
|
||||||
|
use App\Tests\Service\RDAPServiceTest;
|
||||||
|
use PHPUnit\Framework\Attributes\DependsExternal;
|
||||||
|
use Zenstruck\Foundry\Test\Factories;
|
||||||
|
|
||||||
|
final class WatchlistControllerTest extends AbstractTest
|
||||||
|
{
|
||||||
|
use Factories;
|
||||||
|
|
||||||
|
public function testGetWatchlistCollection(): void
|
||||||
|
{
|
||||||
|
$client = $this->createUserAndWatchlist();
|
||||||
|
|
||||||
|
$response = $client->request('GET', '/api/watchlists');
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertMatchesResourceCollectionJsonSchema(WatchList::class);
|
||||||
|
|
||||||
|
$data = $response->toArray();
|
||||||
|
$this->assertArrayHasKey('hydra:member', $data);
|
||||||
|
$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();
|
||||||
|
|
||||||
|
$response = $client->request('GET', '/api/tracked');
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = $response->toArray();
|
||||||
|
$this->assertArrayHasKey('hydra:member', $data);
|
||||||
|
$this->assertCount(1, $data['hydra:member']);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[DependsExternal(RDAPServiceTest::class, 'testUpdateRdapServers')]
|
||||||
|
public function testGetWatchlistFeeds()
|
||||||
|
{
|
||||||
|
$client = $this->createUserAndWatchlist();
|
||||||
|
|
||||||
|
$response = $client->request('GET', '/api/watchlists');
|
||||||
|
$token = $response->toArray()['hydra:member'][0]['token'];
|
||||||
|
|
||||||
|
$client->request('GET', '/api/watchlists/'.$token.'/calendar');
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertResponseHeaderSame('content-type', 'text/calendar; charset=utf-8');
|
||||||
|
|
||||||
|
$client->request('GET', '/api/watchlists/'.$token.'/rss/events');
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertResponseHeaderSame('content-type', 'application/atom+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$client->request('GET', '/api/watchlists/'.$token.'/rss/status');
|
||||||
|
$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/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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user