Comments can now have documents attached via multipart/form-data upload.
New endpoint GET /api/documents/comment/{id} to list a comment's files.
Document entity gains a comment relation with cascade remove.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
247 lines
7.5 KiB
PHP
247 lines
7.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Api\Controller;
|
|
|
|
use App\Tests\AbstractApiTestCase;
|
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
class CommentControllerTest extends AbstractApiTestCase
|
|
{
|
|
public function testCreateComment(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$client = $this->createViewerClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'Test comment',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
'entityName' => 'Machine A',
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(201);
|
|
$this->assertJsonContains([
|
|
'content' => 'Test comment',
|
|
'entityType' => 'machine',
|
|
'status' => 'open',
|
|
]);
|
|
}
|
|
|
|
public function testCreateCommentUnauthenticated(): void
|
|
{
|
|
$client = $this->createUnauthenticatedClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'No auth',
|
|
'entityType' => 'machine',
|
|
'entityId' => 'fake-id',
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(401);
|
|
}
|
|
|
|
public function testCreateCommentEmptyContent(): void
|
|
{
|
|
$client = $this->createViewerClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => '',
|
|
'entityType' => 'machine',
|
|
'entityId' => 'some-id',
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(400);
|
|
$this->assertJsonContains(['message' => 'Le contenu est requis.']);
|
|
}
|
|
|
|
public function testCreateCommentInvalidEntityType(): void
|
|
{
|
|
$client = $this->createViewerClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'Invalid type',
|
|
'entityType' => 'invalid',
|
|
'entityId' => 'some-id',
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(400);
|
|
$this->assertJsonContains(['message' => "Type d'entité invalide."]);
|
|
}
|
|
|
|
public function testCreateCommentMissingEntityId(): void
|
|
{
|
|
$client = $this->createViewerClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'Missing ID',
|
|
'entityType' => 'machine',
|
|
'entityId' => '',
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(400);
|
|
}
|
|
|
|
public function testResolveComment(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$viewerClient = $this->createViewerClient();
|
|
$response = $viewerClient->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'To resolve',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
],
|
|
]);
|
|
|
|
$data = $response->toArray();
|
|
$commentId = $data['id'];
|
|
|
|
$gestionnaireClient = $this->createGestionnaireClient();
|
|
$gestionnaireClient->request('PATCH', sprintf('/api/comments/%s/resolve', $commentId));
|
|
|
|
$this->assertResponseIsSuccessful();
|
|
$this->assertJsonContains(['status' => 'resolved']);
|
|
}
|
|
|
|
public function testResolveCommentNotFound(): void
|
|
{
|
|
$client = $this->createGestionnaireClient();
|
|
$client->request('PATCH', '/api/comments/nonexistent-id/resolve');
|
|
|
|
$this->assertResponseStatusCodeSame(404);
|
|
}
|
|
|
|
public function testUnresolvedCount(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$client = $this->createViewerClient();
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'Open 1',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
],
|
|
]);
|
|
$client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'Open 2',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
],
|
|
]);
|
|
|
|
$client->request('GET', '/api/comments/stats/unresolved-count');
|
|
|
|
$this->assertResponseIsSuccessful();
|
|
$this->assertJsonContains(['count' => 2]);
|
|
}
|
|
|
|
public function testCreateCommentJsonReturnsDocumentsArray(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$client = $this->createViewerClient();
|
|
$response = $client->request('POST', '/api/comments', [
|
|
'json' => [
|
|
'content' => 'No files',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(201);
|
|
$data = $response->toArray();
|
|
$this->assertSame([], $data['documents']);
|
|
}
|
|
|
|
public function testCreateCommentWithFile(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$client = $this->createViewerClient();
|
|
|
|
$tmpFile = tempnam(sys_get_temp_dir(), 'test_');
|
|
file_put_contents($tmpFile, 'test file content');
|
|
|
|
$uploadedFile = new UploadedFile(
|
|
$tmpFile,
|
|
'test-doc.pdf',
|
|
'application/pdf',
|
|
null,
|
|
true,
|
|
);
|
|
|
|
$client->request('POST', '/api/comments', [
|
|
'extra' => [
|
|
'parameters' => [
|
|
'content' => 'Comment with file',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
'entityName' => 'Machine A',
|
|
],
|
|
'files' => [
|
|
'files' => [$uploadedFile],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(201);
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
$this->assertSame('Comment with file', $data['content']);
|
|
$this->assertCount(1, $data['documents']);
|
|
$this->assertSame('test-doc.pdf', $data['documents'][0]['filename']);
|
|
$this->assertArrayHasKey('fileUrl', $data['documents'][0]);
|
|
$this->assertArrayHasKey('downloadUrl', $data['documents'][0]);
|
|
|
|
@unlink($tmpFile);
|
|
}
|
|
|
|
public function testCreateCommentWithMultipleFiles(): void
|
|
{
|
|
$machine = $this->createMachine('Machine A');
|
|
|
|
$client = $this->createViewerClient();
|
|
|
|
$tmpFile1 = tempnam(sys_get_temp_dir(), 'test_');
|
|
file_put_contents($tmpFile1, 'content 1');
|
|
$tmpFile2 = tempnam(sys_get_temp_dir(), 'test_');
|
|
file_put_contents($tmpFile2, 'content 2');
|
|
|
|
$file1 = new UploadedFile($tmpFile1, 'doc1.pdf', 'application/pdf', null, true);
|
|
$file2 = new UploadedFile($tmpFile2, 'doc2.png', 'image/png', null, true);
|
|
|
|
$client->request('POST', '/api/comments', [
|
|
'extra' => [
|
|
'parameters' => [
|
|
'content' => 'Multiple files',
|
|
'entityType' => 'machine',
|
|
'entityId' => $machine->getId(),
|
|
],
|
|
'files' => [
|
|
'files' => [$file1, $file2],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->assertResponseStatusCodeSame(201);
|
|
$data = json_decode($client->getResponse()->getContent(), true);
|
|
$this->assertCount(2, $data['documents']);
|
|
|
|
@unlink($tmpFile1);
|
|
@unlink($tmpFile2);
|
|
}
|
|
}
|