66 lines
4.4 KiB
PHP
66 lines
4.4 KiB
PHP
<?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");
|