feat: complete jobcard management workflows and UI
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../app/Domain/Credential/TechnicalInformation.php';
|
||||
require_once __DIR__ . '/../app/Domain/Credential/TechnicalInformationCommand.php';
|
||||
require_once __DIR__ . '/../app/Domain/Credential/TechnicalInformationRepository.php';
|
||||
|
||||
use App\Domain\Credential\TechnicalInformation;
|
||||
use App\Domain\Credential\TechnicalInformationCommand;
|
||||
use App\Domain\Credential\TechnicalInformationRepository;
|
||||
|
||||
function technical_command_assert_same(mixed $expected, mixed $actual, string $message): void
|
||||
{
|
||||
if ($expected !== $actual) throw new RuntimeException($message . "\nExpected: " . var_export($expected, true) . "\nActual: " . var_export($actual, true));
|
||||
}
|
||||
|
||||
$command = new TechnicalInformationCommand();
|
||||
foreach ([
|
||||
'microsoft' => ['label' => 'Microsoft 365', 'tenant' => 'example.onmicrosoft.com', 'product' => 'Business Premium'],
|
||||
'network' => ['label' => 'Core network', 'hostname' => 'core-sw-01', 'ip_address' => '192.0.2.10', 'vlan' => 20],
|
||||
'router' => ['label' => 'Edge router', 'hostname' => 'edge-01', 'ip_address' => '192.0.2.1', 'model' => 'RB5009'],
|
||||
'infrastructure' => ['label' => 'Production server', 'hostname' => 'app-01', 'role' => 'application'],
|
||||
] as $category => $data) {
|
||||
$result = $command->validate(['client_id' => 7, 'category' => $category, 'data' => $data]);
|
||||
technical_command_assert_same(true, $result['valid'], "{$category} information should validate.");
|
||||
technical_command_assert_same($category, $result['record']['category'], 'Category should be retained in the normalized record.');
|
||||
technical_command_assert_same($data['label'], $result['record']['data']['label'], 'Structured category data should be retained.');
|
||||
}
|
||||
|
||||
$invalid = $command->validate(['client_id' => 7, 'category' => 'router', 'data' => ['label' => 'Router', 'ip_address' => 'not-an-ip', 'unexpected' => 'secret']]);
|
||||
if ($invalid['valid'] || !isset($invalid['errors']['data.ip_address'], $invalid['errors']['data.unexpected'])) {
|
||||
throw new RuntimeException('Structured technical information must reject invalid and unknown fields.');
|
||||
}
|
||||
|
||||
$existing = ['id' => 41, 'client_id' => 7, 'category' => 'network', 'data' => ['label' => 'Core', 'hostname' => 'sw-01', 'vlan' => 10]];
|
||||
$edit = $command->validateEdit($existing, ['data' => ['vlan' => '20', 'notes' => ' Updated ']]);
|
||||
technical_command_assert_same(true, $edit['valid'], 'A technical-information edit should validate merged data.');
|
||||
technical_command_assert_same(20, $edit['record']['data']['vlan'], 'Edit should normalize structured values.');
|
||||
technical_command_assert_same('Updated', $edit['record']['data']['notes'], 'Edit should trim text values.');
|
||||
$delete = $command->validateDelete($existing);
|
||||
technical_command_assert_same(['valid' => true, 'action' => 'delete', 'id' => 41, 'client_id' => 7, 'category' => 'network', 'errors' => []], $delete, 'Delete validation should return an adapter-ready action.');
|
||||
|
||||
$projection = $command->display(['id' => 41, 'client_id' => 7, 'category' => 'router', 'data' => ['label' => 'Edge', 'hostname' => 'edge-01', 'password' => 'do-not-show', 'secret' => 'do-not-show']]);
|
||||
technical_command_assert_same(['id' => 41, 'client_id' => 7, 'category' => 'router', 'data' => ['label' => 'Edge', 'hostname' => 'edge-01']], $projection, 'Display projection must allow-list safe structured fields.');
|
||||
|
||||
final class TechnicalInformationCommandFakePdo extends PDO
|
||||
{
|
||||
public function __construct() {}
|
||||
public function prepare(string $query, array $options = []): PDOStatement|false
|
||||
{
|
||||
return new class($query) extends PDOStatement {
|
||||
public function __construct(private string $query) {}
|
||||
public function execute(?array $params = null): bool { return true; }
|
||||
public function fetch(int $mode = PDO::FETCH_DEFAULT, int ...$args): mixed
|
||||
{
|
||||
return ['id' => 55, 'client_id' => 7, 'category' => 'microsoft', 'data_json' => '{"label":"M365","tenant":"example.onmicrosoft.com"}', 'updated_by' => null, 'created_at' => null, 'updated_at' => null];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
$repository = new TechnicalInformationRepository(new TechnicalInformationCommandFakePdo());
|
||||
$stored = (new TechnicalInformationCommand($repository))->create(7, ['category' => 'microsoft', 'data' => ['label' => 'M365', 'tenant' => 'example.onmicrosoft.com']]);
|
||||
technical_command_assert_same(55, $stored['id'], 'Command should remain compatible with the repository adapter.');
|
||||
|
||||
printf("Technical information command tests: 9 passed\n");
|
||||
Reference in New Issue
Block a user