Files
clinicpro/tests/ApiTestCase.php
T

90 lines
2.9 KiB
PHP

<?php
namespace App\Tests;
use App\Auth\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* Base class for functional API tests.
*
* Provides a booted KernelBrowser, the EntityManager, and helpers to create
* users and issue JWTs so tests can hit authenticated /api and /oauth endpoints.
* Runs against the dedicated db_test database (see .env.test / doctrine when@test).
*/
abstract class ApiTestCase extends WebTestCase
{
protected KernelBrowser $client;
protected EntityManagerInterface $em;
protected function setUp(): void
{
$this->client = static::createClient();
$this->em = static::getContainer()->get(EntityManagerInterface::class);
}
/**
* Persist a user with the given roles. Mobile is randomised per test to
* avoid unique-constraint clashes across cases without a full DB reset.
*/
protected function createUser(array $roles = ['ROLE_USER'], ?string $mobile = null): User
{
// 9 random digits after 09 (full ^09\d{9}$ space) — db_test is never reset,
// so a narrower space eventually collides on the unique mobile.
$mobile ??= '09' . str_pad((string) random_int(0, 999_999_999), 9, '0', STR_PAD_LEFT);
$user = new User($mobile);
$user->setRoles($roles);
$user->setStatus(1);
$this->em->persist($user);
$this->em->flush();
return $user;
}
protected function jwtFor(User $user): string
{
return static::getContainer()
->get(JWTTokenManagerInterface::class)
->create($user);
}
/**
* Issue an authenticated JSON request and return the decoded response body.
*/
protected function authJson(string $method, string $uri, User $user, array $body = []): array
{
$this->client->request(
$method,
$uri,
server: [
'HTTP_AUTHORIZATION' => 'Bearer ' . $this->jwtFor($user),
'CONTENT_TYPE' => 'application/json',
],
content: $body ? json_encode($body) : null,
);
return json_decode($this->client->getResponse()->getContent(), true) ?? [];
}
protected function responseCode(): int
{
return $this->client->getResponse()->getStatusCode();
}
/**
* Count the SQL queries executed while running $fn. Used to assert that a
* list endpoint's query count does not grow with the number of rows (N+1).
*/
protected function countQueries(callable $fn): int
{
$holder = static::getContainer()->get('doctrine.debug_data_holder');
$holder->reset();
$fn();
return array_sum(array_map('count', $holder->getData()));
}
}