feat(machine) : add custom field management on machine detail page
- Fix: return customFieldValues in structure endpoint (was hardcoded null) - Frontend: add editor to create/edit/delete custom field definitions - Tests: add integration tests for structure values + definition CRUD Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Submodule Inventory_frontend updated: 165e0a6341...98f5d983b3
@@ -573,7 +573,7 @@ class MachineStructureController extends AbstractController
|
|||||||
'constructeurs' => $this->normalizeConstructeurs($machine->getConstructeurs()),
|
'constructeurs' => $this->normalizeConstructeurs($machine->getConstructeurs()),
|
||||||
'customFields' => $this->normalizeCustomFields($machine->getCustomFields()),
|
'customFields' => $this->normalizeCustomFields($machine->getCustomFields()),
|
||||||
'documents' => null,
|
'documents' => null,
|
||||||
'customFieldValues' => null,
|
'customFieldValues' => $this->normalizeCustomFieldValues($machine->getCustomFieldValues()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
tests/Api/Controller/MachineCustomFieldDefinitionTest.php
Normal file
122
tests/Api/Controller/MachineCustomFieldDefinitionTest.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\Api\Controller;
|
||||||
|
|
||||||
|
use App\Tests\AbstractApiTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MachineCustomFieldDefinitionTest extends AbstractApiTestCase
|
||||||
|
{
|
||||||
|
public function testCreateCustomFieldForMachine(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine CF Create');
|
||||||
|
|
||||||
|
$client = $this->createGestionnaireClient();
|
||||||
|
$client->request('POST', '/api/custom_fields', [
|
||||||
|
'headers' => ['Content-Type' => 'application/ld+json'],
|
||||||
|
'json' => [
|
||||||
|
'name' => 'Tension',
|
||||||
|
'type' => 'number',
|
||||||
|
'machine' => self::iri('machines', $machine->getId()),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertResponseStatusCodeSame(201);
|
||||||
|
$this->assertJsonContains(['name' => 'Tension', 'type' => 'number']);
|
||||||
|
|
||||||
|
// Verify via structure endpoint
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
$this->assertArrayHasKey('customFields', $data['machine']);
|
||||||
|
$this->assertNotEmpty($data['machine']['customFields'], 'customFields should contain the new field');
|
||||||
|
|
||||||
|
$found = false;
|
||||||
|
foreach ($data['machine']['customFields'] as $cf) {
|
||||||
|
if ('Tension' === $cf['name'] && 'number' === $cf['type']) {
|
||||||
|
$found = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->assertTrue($found, 'Structure should contain the created custom field "Tension"');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateCustomFieldForMachine(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine CF Update');
|
||||||
|
$cf = $this->createCustomField('OldName', 'text', $machine);
|
||||||
|
|
||||||
|
$client = $this->createGestionnaireClient();
|
||||||
|
$client->request('PATCH', self::iri('custom_fields', $cf->getId()), [
|
||||||
|
'headers' => ['Content-Type' => 'application/merge-patch+json'],
|
||||||
|
'json' => ['name' => 'NewName'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertJsonContains(['name' => 'NewName']);
|
||||||
|
|
||||||
|
// Verify via structure endpoint
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
$this->assertNotEmpty($data['machine']['customFields']);
|
||||||
|
|
||||||
|
$names = array_column($data['machine']['customFields'], 'name');
|
||||||
|
$this->assertContains('NewName', $names, 'Structure should reflect the updated custom field name');
|
||||||
|
$this->assertNotContains('OldName', $names, 'Old name should no longer appear');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeleteCustomFieldForMachine(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine CF Delete');
|
||||||
|
$cf = $this->createCustomField('ToDelete', 'text', $machine);
|
||||||
|
|
||||||
|
$client = $this->createGestionnaireClient();
|
||||||
|
$client->request('DELETE', self::iri('custom_fields', $cf->getId()));
|
||||||
|
|
||||||
|
$this->assertResponseStatusCodeSame(204);
|
||||||
|
|
||||||
|
// Verify via structure endpoint
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
$this->assertSame([], $data['machine']['customFields'], 'customFields should be empty after deletion');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddCustomFieldsEndpointInitializesValues(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine CF Values');
|
||||||
|
$cf = $this->createCustomField('Voltage', 'number', $machine);
|
||||||
|
$cf->setDefaultValue('220');
|
||||||
|
$em = $this->getEntityManager();
|
||||||
|
$em->persist($cf);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
|
$client = $this->createGestionnaireClient();
|
||||||
|
$client->request('POST', sprintf('/api/machines/%s/add-custom-fields', $machine->getId()));
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$response = $client->getResponse()->toArray();
|
||||||
|
$this->assertTrue($response['success']);
|
||||||
|
$this->assertNotEmpty($response['customFieldValues'], 'customFieldValues should not be empty after add-custom-fields');
|
||||||
|
|
||||||
|
// Verify via structure endpoint
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
$this->assertNotEmpty($data['machine']['customFieldValues'], 'Structure should contain initialized custom field values');
|
||||||
|
|
||||||
|
$cfv = $data['machine']['customFieldValues'][0];
|
||||||
|
$this->assertSame('220', $cfv['value'], 'Value should match the default value');
|
||||||
|
$this->assertSame('Voltage', $cfv['customField']['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\Api\Controller;
|
||||||
|
|
||||||
|
use App\Tests\AbstractApiTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class MachineStructureCustomFieldValuesTest extends AbstractApiTestCase
|
||||||
|
{
|
||||||
|
public function testStructureIncludesCustomFieldValues(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine CFV');
|
||||||
|
$cf = $this->createCustomField('Tension', 'number', $machine);
|
||||||
|
$this->createCustomFieldValue($cf, '220', $machine);
|
||||||
|
|
||||||
|
$client = $this->createViewerClient();
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('machine', $data);
|
||||||
|
$this->assertArrayHasKey('customFieldValues', $data['machine']);
|
||||||
|
$this->assertIsArray($data['machine']['customFieldValues']);
|
||||||
|
$this->assertNotEmpty($data['machine']['customFieldValues'], 'customFieldValues should not be empty');
|
||||||
|
|
||||||
|
$cfv = $data['machine']['customFieldValues'][0];
|
||||||
|
$this->assertSame('220', $cfv['value']);
|
||||||
|
$this->assertArrayHasKey('customField', $cfv);
|
||||||
|
$this->assertSame('Tension', $cfv['customField']['name']);
|
||||||
|
$this->assertSame('number', $cfv['customField']['type']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStructureReturnsEmptyArrayWhenNoCustomFieldValues(): void
|
||||||
|
{
|
||||||
|
$machine = $this->createMachine('Machine sans CFV');
|
||||||
|
|
||||||
|
$client = $this->createViewerClient();
|
||||||
|
$client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$data = $client->getResponse()->toArray();
|
||||||
|
|
||||||
|
$this->assertArrayHasKey('customFieldValues', $data['machine']);
|
||||||
|
$this->assertSame([], $data['machine']['customFieldValues']);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user