Files
Lesstime/tests/Functional/Module/ProjectManagement/ProjectCreationWorkflowTest.php
T
Matthieu d3abb584a9
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 38s
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m39s
fix(project) : permet de choisir un workflow à la création + filet par défaut
La création de projet échouait : `Project.workflow` est obligatoire mais
n'était jamais fourni (formulaire frontend, MCP create-project), tout POST
/api/projects partait en erreur de validation/contrainte NOT NULL.

- ProjectDefaultWorkflowListener (prePersist) : assigne le workflow par
  défaut quand aucun n'est fourni, couvrant API Platform, API brute et MCP.
- retrait de l'Assert\NotNull sur Project::workflow (la validation tournait
  avant le flush et empêchait le filet) ; la contrainte DB reste le garde-fou.
- CreateProjectTool (MCP) : paramètre optionnel workflowId.
- ProjectDrawer : sélecteur Workflow en création, pré-rempli sur le défaut,
  IRI envoyée dans le payload.
- tests fonctionnels : création avec et sans workflow.
2026-06-26 16:42:02 +02:00

93 lines
3.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Tests\Functional\Module\ProjectManagement;
use App\Module\Core\Domain\Entity\Permission;
use App\Module\Core\Domain\Entity\User;
use App\Module\ProjectManagement\Domain\Entity\Workflow;
use App\Module\ProjectManagement\Domain\Repository\WorkflowRepositoryInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* Vérifie que la création d'un projet fonctionne avec ou sans workflow fourni :
* - sans workflow → le workflow par défaut est assigné par le listener prePersist
* - avec workflow → le workflow choisi est conservé.
*
* @internal
*/
final class ProjectCreationWorkflowTest extends WebTestCase
{
public function testCreateProjectWithoutWorkflowAssignsDefault(): void
{
$client = self::createClient();
$em = self::getContainer()->get(EntityManagerInterface::class);
$client->loginUser($this->createManager($em));
$client->request('POST', '/api/projects', server: [
'CONTENT_TYPE' => 'application/ld+json',
], content: json_encode([
'code' => $this->randomCode(),
'name' => 'Projet sans workflow',
]));
self::assertResponseStatusCodeSame(201);
$data = json_decode($client->getResponse()->getContent(), true);
self::assertArrayHasKey('workflow', $data);
self::assertNotNull($data['workflow'], 'Un workflow par défaut doit avoir été assigné.');
}
public function testCreateProjectWithExplicitWorkflow(): void
{
$client = self::createClient();
$em = self::getContainer()->get(EntityManagerInterface::class);
$workflow = self::getContainer()->get(WorkflowRepositoryInterface::class)->findDefault()
?? $em->getRepository(Workflow::class)->findOneBy([]);
self::assertInstanceOf(Workflow::class, $workflow, 'Les fixtures doivent fournir au moins un workflow.');
$client->loginUser($this->createManager($em));
$client->request('POST', '/api/projects', server: [
'CONTENT_TYPE' => 'application/ld+json',
], content: json_encode([
'code' => $this->randomCode(),
'name' => 'Projet avec workflow',
'workflow' => '/api/workflows/'.$workflow->getId(),
]));
self::assertResponseStatusCodeSame(201);
$data = json_decode($client->getResponse()->getContent(), true);
self::assertSame($workflow->getId(), $data['workflow']['id'] ?? null);
}
private function createManager(EntityManagerInterface $em): User
{
$permission = $em->getRepository(Permission::class)->findOneBy(['code' => 'project-management.projects.manage']);
self::assertInstanceOf(Permission::class, $permission, 'Lancer app:sync-permissions pour project-management.projects.manage.');
$user = new User();
$user->setUsername('proj-create-'.uniqid());
$user->setPassword('x');
$user->setRoles(['ROLE_USER']);
$user->addDirectPermission($permission);
$em->persist($user);
$em->flush();
return $user;
}
private function randomCode(): string
{
$letters = '';
for ($i = 0; $i < 6; ++$i) {
$letters .= chr(random_int(65, 90));
}
return $letters;
}
}