test: ajout tests SetPasswordController, SonarBadgeController, StatusPageController, WebhookDocuSealController
tests/Controller/SetPasswordControllerTest.php (nouveau, 5 tests): - testGetFormRendered: token valide, affiche le formulaire - testTokenExpired: token invalide, affiche la page expired - testPostPasswordTooShort: mot de passe < 8 caracteres, erreur - testPostPasswordMismatch: confirmation differente, erreur - testPostSuccess: mot de passe valide, flush + redirect 302 tests/Controller/SonarBadgeControllerTest.php (nouveau, 2 tests): - testBadgeSuccess: metric valide, retourne SVG avec Content-Type image/svg+xml - testBadgeInvalidMetric: metric invalide, retourne 404 tests/Controller/StatusPageControllerTest.php (reecrit, 2 tests): - testIndexEmpty: aucune categorie, retourne 200 - testIndexWithServices: categorie avec service, QueryBuilder mocke pour les logs, retourne 200 tests/Controller/WebhookDocuSealControllerTest.php (nouveau, 9 tests): - testUnauthorized: mauvais secret dans le header, retourne 401 - testInvalidPayload: JSON invalide, retourne 400 - testIgnoredDocType: doc_type autre que attestation, retourne ignored - testEmptySecret: secret vide bypass la verification - testFormViewedAttestationNotFound: attestation introuvable, retourne 404 - testFormViewedAttestationFound: attestation trouvee, retourne 200 - testFormStarted: evenement started, retourne 200 - testFormDeclined: evenement declined, retourne 200 - testUnknownEvent: evenement inconnu, retourne ignored Resultat: 368 tests, 718 assertions, 0 failures, 0 notices Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
145
tests/Controller/SetPasswordControllerTest.php
Normal file
145
tests/Controller/SetPasswordControllerTest.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Controller\SetPasswordController;
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
class SetPasswordControllerTest extends TestCase
|
||||
{
|
||||
private function createController(Request $request): SetPasswordController
|
||||
{
|
||||
$twig = $this->createStub(Environment::class);
|
||||
$twig->method('render')->willReturn('<html></html>');
|
||||
$router = $this->createStub(RouterInterface::class);
|
||||
$router->method('generate')->willReturn('/');
|
||||
$requestStack = new RequestStack();
|
||||
$requestStack->push($request);
|
||||
|
||||
$container = $this->createStub(ContainerInterface::class);
|
||||
$container->method('has')->willReturn(true);
|
||||
$container->method('get')->willReturnMap([
|
||||
['twig', $twig],
|
||||
['router', $router],
|
||||
['request_stack', $requestStack],
|
||||
]);
|
||||
|
||||
$controller = new SetPasswordController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
public function testGetFormRendered(): void
|
||||
{
|
||||
$user = new User();
|
||||
$user->setEmail('t@t.com');
|
||||
$user->setFirstName('T');
|
||||
$user->setLastName('T');
|
||||
$user->setPassword('h');
|
||||
$user->setTempPassword('valid-token');
|
||||
|
||||
$repo = $this->createStub(UserRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($user);
|
||||
|
||||
$request = new Request();
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$controller = $this->createController($request);
|
||||
|
||||
$response = $controller->index('valid-token', $request, $repo, $this->createStub(UserPasswordHasherInterface::class), $this->createStub(EntityManagerInterface::class));
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testTokenExpired(): void
|
||||
{
|
||||
$repo = $this->createStub(UserRepository::class);
|
||||
$repo->method('findOneBy')->willReturn(null);
|
||||
|
||||
$request = new Request();
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$controller = $this->createController($request);
|
||||
|
||||
$response = $controller->index('bad-token', $request, $repo, $this->createStub(UserPasswordHasherInterface::class), $this->createStub(EntityManagerInterface::class));
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testPostPasswordTooShort(): void
|
||||
{
|
||||
$user = new User();
|
||||
$user->setEmail('t@t.com');
|
||||
$user->setFirstName('T');
|
||||
$user->setLastName('T');
|
||||
$user->setPassword('h');
|
||||
$user->setTempPassword('token');
|
||||
|
||||
$repo = $this->createStub(UserRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($user);
|
||||
|
||||
$request = new Request([], ['password' => 'short', 'password_confirm' => 'short']);
|
||||
$request->setMethod('POST');
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$controller = $this->createController($request);
|
||||
|
||||
$response = $controller->index('token', $request, $repo, $this->createStub(UserPasswordHasherInterface::class), $this->createStub(EntityManagerInterface::class));
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testPostPasswordMismatch(): void
|
||||
{
|
||||
$user = new User();
|
||||
$user->setEmail('t@t.com');
|
||||
$user->setFirstName('T');
|
||||
$user->setLastName('T');
|
||||
$user->setPassword('h');
|
||||
$user->setTempPassword('token');
|
||||
|
||||
$repo = $this->createStub(UserRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($user);
|
||||
|
||||
$request = new Request([], ['password' => 'password123', 'password_confirm' => 'different123']);
|
||||
$request->setMethod('POST');
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$controller = $this->createController($request);
|
||||
|
||||
$response = $controller->index('token', $request, $repo, $this->createStub(UserPasswordHasherInterface::class), $this->createStub(EntityManagerInterface::class));
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testPostSuccess(): void
|
||||
{
|
||||
$user = new User();
|
||||
$user->setEmail('t@t.com');
|
||||
$user->setFirstName('T');
|
||||
$user->setLastName('T');
|
||||
$user->setPassword('h');
|
||||
$user->setTempPassword('token');
|
||||
|
||||
$repo = $this->createStub(UserRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($user);
|
||||
|
||||
$hasher = $this->createStub(UserPasswordHasherInterface::class);
|
||||
$hasher->method('hashPassword')->willReturn('hashed');
|
||||
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$em->expects($this->once())->method('flush');
|
||||
|
||||
$request = new Request([], ['password' => 'newpassword8', 'password_confirm' => 'newpassword8']);
|
||||
$request->setMethod('POST');
|
||||
$request->setSession(new Session(new MockArraySessionStorage()));
|
||||
$controller = $this->createController($request);
|
||||
|
||||
$response = $controller->index('token', $request, $repo, $hasher, $em);
|
||||
$this->assertSame(302, $response->getStatusCode());
|
||||
}
|
||||
}
|
||||
38
tests/Controller/SonarBadgeControllerTest.php
Normal file
38
tests/Controller/SonarBadgeControllerTest.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Controller\SonarBadgeController;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Symfony\Contracts\HttpClient\ResponseInterface;
|
||||
|
||||
class SonarBadgeControllerTest extends TestCase
|
||||
{
|
||||
public function testBadgeSuccess(): void
|
||||
{
|
||||
$httpResponse = $this->createStub(ResponseInterface::class);
|
||||
$httpResponse->method('getContent')->willReturn('<svg>badge</svg>');
|
||||
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
$httpClient->method('request')->willReturn($httpResponse);
|
||||
|
||||
$controller = new SonarBadgeController();
|
||||
$response = $controller->badge('coverage', $httpClient, 'https://sonar.test', 'project', 'token');
|
||||
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$this->assertSame('image/svg+xml', $response->headers->get('Content-Type'));
|
||||
$this->assertSame('<svg>badge</svg>', $response->getContent());
|
||||
}
|
||||
|
||||
public function testBadgeInvalidMetric(): void
|
||||
{
|
||||
$httpClient = $this->createStub(HttpClientInterface::class);
|
||||
|
||||
$controller = new SonarBadgeController();
|
||||
$response = $controller->badge('invalid_metric', $httpClient, 'https://sonar.test', 'project', 'token');
|
||||
|
||||
$this->assertSame(404, $response->getStatusCode());
|
||||
}
|
||||
}
|
||||
@@ -5,41 +5,75 @@ namespace App\Tests\Controller;
|
||||
use App\Controller\StatusPageController;
|
||||
use App\Entity\Service;
|
||||
use App\Entity\ServiceCategory;
|
||||
use App\Entity\ServiceMessage;
|
||||
use App\Repository\ServiceCategoryRepository;
|
||||
use App\Repository\ServiceRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Twig\Environment;
|
||||
|
||||
class StatusPageControllerTest extends TestCase
|
||||
{
|
||||
public function testIndex(): void
|
||||
public function testIndexEmpty(): void
|
||||
{
|
||||
$categoryRepo = $this->createStub(ServiceCategoryRepository::class);
|
||||
$serviceRepo = $this->createStub(ServiceRepository::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
$twig->method('render')->willReturn('<html></html>');
|
||||
|
||||
$container = $this->createStub(ContainerInterface::class);
|
||||
$container->method('has')->willReturn(true);
|
||||
$container->method('get')->willReturnMap([['twig', $twig]]);
|
||||
|
||||
$catRepo = $this->createStub(ServiceCategoryRepository::class);
|
||||
$catRepo->method('findBy')->willReturn([]);
|
||||
|
||||
$svcRepo = $this->createStub(ServiceRepository::class);
|
||||
|
||||
$msgRepo = $this->createStub(EntityRepository::class);
|
||||
$msgRepo->method('findBy')->willReturn([]);
|
||||
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$em->method('getRepository')->willReturn($msgRepo);
|
||||
|
||||
$category = new ServiceCategory('Web', 'web');
|
||||
$service = new Service('Website', 'website', $category);
|
||||
$service->setStatus('up');
|
||||
// Manual addition since it's not persisted
|
||||
$ref = new \ReflectionProperty(ServiceCategory::class, 'services');
|
||||
$ref->setValue($category, new ArrayCollection([$service]));
|
||||
$controller = new StatusPageController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
$categoryRepo->method('findBy')->willReturn([$category]);
|
||||
$serviceRepo->method('getHistoryForDays')->willReturn([]);
|
||||
$serviceRepo->method('getDailyStatus')->willReturn([]);
|
||||
$response = $controller->index($catRepo, $svcRepo, $em);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
$messageRepo = $this->createStub(EntityRepository::class);
|
||||
$messageRepo->method('findBy')->willReturn([]);
|
||||
$em->method('getRepository')->willReturn($messageRepo);
|
||||
#[AllowMockObjectsWithoutExpectations]
|
||||
public function testIndexWithServices(): void
|
||||
{
|
||||
$twig = $this->createStub(Environment::class);
|
||||
$twig->method('render')->willReturn('<html></html>');
|
||||
|
||||
$container = $this->createStub(ContainerInterface::class);
|
||||
$container->method('has')->willReturn(true);
|
||||
$container->method('get')->willReturnMap([['twig', $twig]]);
|
||||
|
||||
$category = new ServiceCategory('Infra', 'infra');
|
||||
$service = new Service('Esy-Web', 'esy-web', $category);
|
||||
|
||||
$catRepo = $this->createStub(ServiceCategoryRepository::class);
|
||||
$catRepo->method('findBy')->willReturn([$category]);
|
||||
|
||||
$svcRepo = $this->createStub(ServiceRepository::class);
|
||||
$svcRepo->method('getHistoryForDays')->willReturn([]);
|
||||
$svcRepo->method('getDailyStatus')->willReturn([]);
|
||||
|
||||
$msgRepo = $this->createStub(EntityRepository::class);
|
||||
$msgRepo->method('findBy')->willReturn([]);
|
||||
|
||||
$query = $this->getMockBuilder(Query::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['getResult', 'getSQL', 'execute'])
|
||||
->getMock();
|
||||
$query->method('getResult')->willReturn([]);
|
||||
|
||||
$qb = $this->createStub(QueryBuilder::class);
|
||||
$qb->method('select')->willReturn($qb);
|
||||
@@ -48,30 +82,16 @@ class StatusPageControllerTest extends TestCase
|
||||
$qb->method('andWhere')->willReturn($qb);
|
||||
$qb->method('setParameter')->willReturn($qb);
|
||||
$qb->method('orderBy')->willReturn($qb);
|
||||
|
||||
$query = $this->createStub(Query::class);
|
||||
$query->method('getResult')->willReturn([]);
|
||||
$qb->method('getQuery')->willReturn($query);
|
||||
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$em->method('getRepository')->willReturn($msgRepo);
|
||||
$em->method('createQueryBuilder')->willReturn($qb);
|
||||
|
||||
$twig = $this->createStub(Environment::class);
|
||||
$twig->method('render')->willReturn('<html></html>');
|
||||
|
||||
$container = $this->createStub(ContainerInterface::class);
|
||||
$container->method('has')->willReturnMap([
|
||||
['twig', true],
|
||||
['parameter_bag', true],
|
||||
]);
|
||||
$container->method('get')->willReturnMap([
|
||||
['twig', $twig],
|
||||
]);
|
||||
|
||||
$controller = new StatusPageController();
|
||||
$controller->setContainer($container);
|
||||
|
||||
$response = $controller->index($categoryRepo, $serviceRepo, $em);
|
||||
|
||||
$this->assertInstanceOf(Response::class, $response);
|
||||
$this->assertEquals('<html></html>', $response->getContent());
|
||||
$response = $controller->index($catRepo, $svcRepo, $em);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
158
tests/Controller/WebhookDocuSealControllerTest.php
Normal file
158
tests/Controller/WebhookDocuSealControllerTest.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Controller\WebhookDocuSealController;
|
||||
use App\Entity\Attestation;
|
||||
use App\Repository\AttestationRepository;
|
||||
use App\Service\MailerService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Twig\Environment;
|
||||
|
||||
class WebhookDocuSealControllerTest extends TestCase
|
||||
{
|
||||
private function invoke(array $payload, string $secret = 'test', string $headerSecret = 'X-Sign', string $headerValue = 'test'): JsonResponse
|
||||
{
|
||||
$controller = new WebhookDocuSealController();
|
||||
$repo = $this->createStub(AttestationRepository::class);
|
||||
$mailer = $this->createStub(MailerService::class);
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
$twig->method('render')->willReturn('<html></html>');
|
||||
|
||||
$request = new Request([], [], [], [], [], [], json_encode($payload));
|
||||
$request->headers->set($headerSecret, $headerValue);
|
||||
$request->headers->set('Content-Type', 'application/json');
|
||||
|
||||
return $controller->__invoke($request, $repo, $mailer, $em, $twig, $headerSecret, $secret, '/tmp');
|
||||
}
|
||||
|
||||
public function testUnauthorized(): void
|
||||
{
|
||||
$response = $this->invoke([], 'correct-secret', 'X-Sign', 'wrong-secret');
|
||||
$this->assertSame(401, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testInvalidPayload(): void
|
||||
{
|
||||
$controller = new WebhookDocuSealController();
|
||||
$repo = $this->createStub(AttestationRepository::class);
|
||||
$mailer = $this->createStub(MailerService::class);
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
|
||||
$request = new Request([], [], [], [], [], [], 'invalid json{{{');
|
||||
$request->headers->set('X-Sign', 'test');
|
||||
|
||||
$response = $controller->__invoke($request, $repo, $mailer, $em, $twig, 'X-Sign', 'test', '/tmp');
|
||||
$this->assertSame(400, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testIgnoredDocType(): void
|
||||
{
|
||||
$response = $this->invoke([
|
||||
'event_type' => 'form.viewed',
|
||||
'data' => ['id' => 1, 'metadata' => ['doc_type' => 'other']],
|
||||
]);
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertSame('ignored', $data['status']);
|
||||
}
|
||||
|
||||
public function testEmptySecret(): void
|
||||
{
|
||||
$response = $this->invoke(['event_type' => 'form.viewed', 'data' => []], '', 'X-Sign', '');
|
||||
// Empty secret = bypass verification
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testFormViewedAttestationNotFound(): void
|
||||
{
|
||||
$response = $this->invoke([
|
||||
'event_type' => 'form.viewed',
|
||||
'data' => ['id' => 999, 'metadata' => ['doc_type' => 'attestation', 'reference' => 'REF-123']],
|
||||
]);
|
||||
|
||||
$this->assertSame(404, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testFormViewedAttestationFound(): void
|
||||
{
|
||||
$attestation = new Attestation('access', '1.1.1.1', 't@t.com', 'secret');
|
||||
|
||||
$controller = new WebhookDocuSealController();
|
||||
$repo = $this->createStub(AttestationRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($attestation);
|
||||
|
||||
$mailer = $this->createStub(MailerService::class);
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
|
||||
$request = new Request([], [], [], [], [], [], json_encode([
|
||||
'event_type' => 'form.viewed',
|
||||
'data' => ['id' => 1, 'metadata' => ['doc_type' => 'attestation', 'reference' => $attestation->getReference()]],
|
||||
]));
|
||||
$request->headers->set('X-Sign', 'test');
|
||||
|
||||
$response = $controller->__invoke($request, $repo, $mailer, $em, $twig, 'X-Sign', 'test', '/tmp');
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testFormStarted(): void
|
||||
{
|
||||
$attestation = new Attestation('access', '1.1.1.1', 't@t.com', 'secret');
|
||||
|
||||
$repo = $this->createStub(AttestationRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($attestation);
|
||||
|
||||
$controller = new WebhookDocuSealController();
|
||||
$mailer = $this->createStub(MailerService::class);
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
|
||||
$request = new Request([], [], [], [], [], [], json_encode([
|
||||
'event_type' => 'form.started',
|
||||
'data' => ['id' => 1, 'metadata' => ['doc_type' => 'attestation']],
|
||||
]));
|
||||
$request->headers->set('X-Sign', 'test');
|
||||
|
||||
$response = $controller->__invoke($request, $repo, $mailer, $em, $twig, 'X-Sign', 'test', '/tmp');
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testFormDeclined(): void
|
||||
{
|
||||
$attestation = new Attestation('access', '1.1.1.1', 't@t.com', 'secret');
|
||||
|
||||
$repo = $this->createStub(AttestationRepository::class);
|
||||
$repo->method('findOneBy')->willReturn($attestation);
|
||||
|
||||
$controller = new WebhookDocuSealController();
|
||||
$mailer = $this->createStub(MailerService::class);
|
||||
$em = $this->createStub(EntityManagerInterface::class);
|
||||
$twig = $this->createStub(Environment::class);
|
||||
|
||||
$request = new Request([], [], [], [], [], [], json_encode([
|
||||
'event_type' => 'form.declined',
|
||||
'data' => ['id' => 1, 'metadata' => ['doc_type' => 'attestation']],
|
||||
]));
|
||||
$request->headers->set('X-Sign', 'test');
|
||||
|
||||
$response = $controller->__invoke($request, $repo, $mailer, $em, $twig, 'X-Sign', 'test', '/tmp');
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testUnknownEvent(): void
|
||||
{
|
||||
$response = $this->invoke([
|
||||
'event_type' => 'form.unknown',
|
||||
'data' => ['id' => 1, 'metadata' => ['doc_type' => 'attestation']],
|
||||
]);
|
||||
|
||||
$data = json_decode($response->getContent(), true);
|
||||
$this->assertSame('ignored', $data['status']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user