Files

66 lines
4.4 KiB
PHP
Raw Permalink Normal View History

<?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");