Add conformite page, SonarQube badge proxy, coverage fixes, and code quality
- Add /conformite page: PSD2/3DS/Stripe, SonarQube badges, CI/CD, security - Create SonarBadgeController proxy to serve SonarQube badges without exposing token - Store SonarQube badge token in ansible/vault.yml instead of env files - Add Meilisearch coverage tests: search with results, search error, sync, delete - Fix MeilisearchService delete catch block with comment - Fix ESLint: use globalThis.confirm instead of window.confirm - Fix accessibility: add for/id attributes to buyer creation form labels - Add conformite link to site footer - Add SonarBadgeControllerTest and LegalControllerTest for /conformite Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,13 +91,24 @@ class AdminControllerTest extends WebTestCase
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
|
||||
public function testSyncMeilisearch(): void
|
||||
public function testSyncMeilisearchWithBuyers(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$em = static::getContainer()->get(EntityManagerInterface::class);
|
||||
$admin = $this->createUser(['ROLE_ROOT']);
|
||||
|
||||
$buyer = new User();
|
||||
$buyer->setEmail('test-sync-'.uniqid().'@example.com');
|
||||
$buyer->setFirstName('Sync');
|
||||
$buyer->setLastName('Test');
|
||||
$buyer->setPassword('$2y$13$hashed');
|
||||
$buyer->setIsVerified(true);
|
||||
$em->persist($buyer);
|
||||
$em->flush();
|
||||
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$meilisearch->expects(self::once())->method('createIndexIfNotExists');
|
||||
$meilisearch->expects(self::once())->method('addDocuments');
|
||||
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
||||
|
||||
$client->loginUser($admin);
|
||||
@@ -106,6 +117,49 @@ class AdminControllerTest extends WebTestCase
|
||||
self::assertResponseRedirects('/admin');
|
||||
}
|
||||
|
||||
public function testBuyersSearchWithMeilisearchError(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$admin = $this->createUser(['ROLE_ROOT']);
|
||||
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$meilisearch->method('search')->willThrowException(new \RuntimeException('Meilisearch down'));
|
||||
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
||||
|
||||
$client->loginUser($admin);
|
||||
$client->request('GET', '/admin/acheteurs?q=test');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
|
||||
public function testBuyersSearchWithResults(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$em = static::getContainer()->get(EntityManagerInterface::class);
|
||||
$admin = $this->createUser(['ROLE_ROOT']);
|
||||
|
||||
$buyer = new User();
|
||||
$buyer->setEmail('test-search-hit-'.uniqid().'@example.com');
|
||||
$buyer->setFirstName('Found');
|
||||
$buyer->setLastName('User');
|
||||
$buyer->setPassword('$2y$13$hashed');
|
||||
$buyer->setIsVerified(true);
|
||||
$em->persist($buyer);
|
||||
$em->flush();
|
||||
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$meilisearch->method('search')->willReturn([
|
||||
'hits' => [['id' => $buyer->getId()]],
|
||||
'estimatedTotalHits' => 1,
|
||||
]);
|
||||
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
||||
|
||||
$client->loginUser($admin);
|
||||
$client->request('GET', '/admin/acheteurs?q=Found');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
|
||||
public function testCreateBuyerWithValidData(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
@@ -210,6 +264,10 @@ class AdminControllerTest extends WebTestCase
|
||||
$em->flush();
|
||||
$buyerId = $buyer->getId();
|
||||
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$meilisearch->expects(self::once())->method('deleteDocument')->with('buyers', $buyerId);
|
||||
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
||||
|
||||
$client->loginUser($admin);
|
||||
$client->request('POST', '/admin/acheteur/'.$buyerId.'/supprimer');
|
||||
|
||||
@@ -219,6 +277,32 @@ class AdminControllerTest extends WebTestCase
|
||||
self::assertNull($deleted);
|
||||
}
|
||||
|
||||
public function testDeleteBuyerMeilisearchFailureDoesNotBlock(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$em = static::getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$admin = $this->createUser(['ROLE_ROOT']);
|
||||
|
||||
$buyer = new User();
|
||||
$buyer->setEmail('test-delete-fail-'.uniqid().'@example.com');
|
||||
$buyer->setFirstName('DeleteFail');
|
||||
$buyer->setLastName('Test');
|
||||
$buyer->setPassword('$2y$13$hashed');
|
||||
$em->persist($buyer);
|
||||
$em->flush();
|
||||
$buyerId = $buyer->getId();
|
||||
|
||||
$meilisearch = $this->createMock(MeilisearchService::class);
|
||||
$meilisearch->method('deleteDocument')->willThrowException(new \RuntimeException('Meilisearch down'));
|
||||
static::getContainer()->set(MeilisearchService::class, $meilisearch);
|
||||
|
||||
$client->loginUser($admin);
|
||||
$client->request('POST', '/admin/acheteur/'.$buyerId.'/supprimer');
|
||||
|
||||
self::assertResponseRedirects('/admin/acheteurs');
|
||||
}
|
||||
|
||||
public function testForceVerification(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
@@ -53,4 +53,12 @@ class LegalControllerTest extends WebTestCase
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
|
||||
public function testConformite(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/conformite');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
}
|
||||
|
||||
24
tests/Controller/SonarBadgeControllerTest.php
Normal file
24
tests/Controller/SonarBadgeControllerTest.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class SonarBadgeControllerTest extends WebTestCase
|
||||
{
|
||||
public function testBadgeWithValidMetric(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/badge/sonar/alert_status.svg');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
}
|
||||
|
||||
public function testBadgeWithInvalidMetric(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/badge/sonar/invalid_metric.svg');
|
||||
|
||||
self::assertResponseStatusCodeSame(404);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ describe('admin.js', () => {
|
||||
beforeEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
vi.restoreAllMocks()
|
||||
window.confirm = vi.fn()
|
||||
globalThis.confirm = vi.fn()
|
||||
})
|
||||
|
||||
it('prevents form submit when confirm is cancelled', async () => {
|
||||
@@ -14,7 +14,7 @@ describe('admin.js', () => {
|
||||
</form>
|
||||
`
|
||||
|
||||
window.confirm.mockReturnValue(false)
|
||||
globalThis.confirm.mockReturnValue(false)
|
||||
|
||||
await import('../../assets/admin.js')
|
||||
document.dispatchEvent(new Event('DOMContentLoaded'))
|
||||
@@ -23,7 +23,7 @@ describe('admin.js', () => {
|
||||
const event = new Event('submit', { cancelable: true })
|
||||
form.dispatchEvent(event)
|
||||
|
||||
expect(window.confirm).toHaveBeenCalledWith('Are you sure?')
|
||||
expect(globalThis.confirm).toHaveBeenCalledWith('Are you sure?')
|
||||
expect(event.defaultPrevented).toBe(true)
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('admin.js', () => {
|
||||
</form>
|
||||
`
|
||||
|
||||
window.confirm.mockReturnValue(true)
|
||||
globalThis.confirm.mockReturnValue(true)
|
||||
|
||||
await import('../../assets/admin.js')
|
||||
document.dispatchEvent(new Event('DOMContentLoaded'))
|
||||
@@ -43,7 +43,7 @@ describe('admin.js', () => {
|
||||
const event = new Event('submit', { cancelable: true })
|
||||
form.dispatchEvent(event)
|
||||
|
||||
expect(window.confirm).toHaveBeenCalledWith('Are you sure?')
|
||||
expect(globalThis.confirm).toHaveBeenCalledWith('Are you sure?')
|
||||
expect(event.defaultPrevented).toBe(false)
|
||||
})
|
||||
|
||||
@@ -61,7 +61,7 @@ describe('admin.js', () => {
|
||||
const event = new Event('submit', { cancelable: true })
|
||||
form.dispatchEvent(event)
|
||||
|
||||
expect(window.confirm).not.toHaveBeenCalled()
|
||||
expect(globalThis.confirm).not.toHaveBeenCalled()
|
||||
expect(event.defaultPrevented).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user