feat(mcp) : add CRUD tools for Sites, Constructeurs, Products

- 5 tools each: list, get, create, update, delete
- McpToolHelper extracted to AbstractApiTestCase for reuse
- DashboardStatsToolTest simplified to use base helpers
- 22 MCP tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-16 14:31:15 +01:00
parent e335f4c24c
commit 4f1e136dc5
20 changed files with 1184 additions and 90 deletions

View File

@@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
namespace App\Tests\Mcp\Tool\Product;
use App\Enum\ModelCategory;
use App\Tests\AbstractApiTestCase;
/**
* @internal
*/
class ProductsCrudToolTest extends AbstractApiTestCase
{
public function testListProducts(): void
{
$this->createProduct(name: 'Product Alpha');
$this->createProduct(name: 'Product Beta');
$session = $this->createMcpClient('ROLE_VIEWER');
$data = $this->callMcpTool($session, 'list_products');
$this->assertArrayHasKey('_parsed', $data);
$this->assertGreaterThanOrEqual(2, $data['_parsed']['total']);
}
public function testGetProduct(): void
{
$constructeur = $this->createConstructeur(name: 'Fournisseur A');
$modelType = $this->createModelType(name: 'Type Produit', code: 'TP-001', category: ModelCategory::PRODUCT);
$product = $this->createProduct(name: 'Product Gamma', reference: 'REF-001', type: $modelType);
// Add constructeur to product
$product->addConstructeur($constructeur);
$this->getEntityManager()->flush();
$session = $this->createMcpClient('ROLE_VIEWER');
$data = $this->callMcpTool($session, 'get_product', ['productId' => $product->getId()]);
$this->assertArrayHasKey('_parsed', $data);
$this->assertSame('Product Gamma', $data['_parsed']['name']);
$this->assertSame('REF-001', $data['_parsed']['reference']);
$this->assertNotNull($data['_parsed']['typeProduct']);
$this->assertSame('Type Produit', $data['_parsed']['typeProduct']['name']);
$this->assertCount(1, $data['_parsed']['constructeurs']);
$this->assertSame('Fournisseur A', $data['_parsed']['constructeurs'][0]['name']);
}
public function testCreateProduct(): void
{
$session = $this->createMcpClient('ROLE_GESTIONNAIRE');
$data = $this->callMcpTool($session, 'create_product', [
'name' => 'Product Nouveau',
'reference' => 'REF-NEW',
'supplierPrice' => '42.99',
]);
$this->assertArrayHasKey('_parsed', $data);
$this->assertSame('Product Nouveau', $data['_parsed']['name']);
$this->assertNotEmpty($data['_parsed']['id']);
}
public function testCreateProductRequiresGestionnaire(): void
{
$session = $this->createMcpClient('ROLE_VIEWER');
$data = $this->callMcpTool($session, 'create_product', ['name' => 'Forbidden']);
$this->assertArrayHasKey('error', $data, 'Should fail with VIEWER role');
}
public function testUpdateProduct(): void
{
$product = $this->createProduct(name: 'Old Product');
$session = $this->createMcpClient('ROLE_GESTIONNAIRE');
$data = $this->callMcpTool($session, 'update_product', [
'productId' => $product->getId(),
'name' => 'Updated Product',
'supplierPrice' => '99.00',
]);
$this->assertArrayHasKey('_parsed', $data);
$this->assertSame('Updated Product', $data['_parsed']['name']);
}
public function testDeleteProduct(): void
{
$product = $this->createProduct(name: 'To Delete');
$session = $this->createMcpClient('ROLE_GESTIONNAIRE');
$data = $this->callMcpTool($session, 'delete_product', ['productId' => $product->getId()]);
$this->assertArrayHasKey('_parsed', $data);
$this->assertTrue($data['_parsed']['deleted']);
}
}