Files
breadcrumb-the-shire/modules/security/tests/Module/Security/Service/SecurityCheckTemplateServiceTest.php

206 lines
7.8 KiB
PHP

<?php
namespace MintyPHP\Tests\Module\Security\Service;
use MintyPHP\Module\Security\Repository\SecurityCheckTemplateRepository;
use MintyPHP\Module\Security\Service\SecurityCheckTemplateService;
use PHPUnit\Framework\TestCase;
class SecurityCheckTemplateServiceTest extends TestCase
{
private const TENANT_ID = 1;
public function testCreateRejectsEmptyCode(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->expects($this->never())->method('insert');
$service = new SecurityCheckTemplateService($repo);
$result = $service->create(self::TENANT_ID, '', 'Name', 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('product_code', $result['errors']);
}
public function testCreateRejectsInvalidCode(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$service = new SecurityCheckTemplateService($repo);
$result = $service->create(self::TENANT_ID, 'has spaces!', 'Name', 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('product_code', $result['errors']);
}
public function testCreateRejectsDuplicateCode(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('codeExists')->willReturn(true);
$service = new SecurityCheckTemplateService($repo);
$result = $service->create(self::TENANT_ID, 'intranet', 'Intranet', 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('product_code', $result['errors']);
}
public function testCreateSucceeds(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('codeExists')->willReturn(false);
$repo->method('insert')->willReturn(12);
$service = new SecurityCheckTemplateService($repo);
$result = $service->create(self::TENANT_ID, 'intranet', 'Intranet', 1);
$this->assertTrue($result['ok']);
$this->assertSame(12, $result['id']);
}
public function testSaveTechSchemaRejectsMissingTemplate(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(null);
$repo->expects($this->never())->method('updateSchema');
$service = new SecurityCheckTemplateService($repo);
$result = $service->saveTechSchema(self::TENANT_ID, 99, [['type' => 'check', 'label' => 'X']], 1);
$this->assertFalse($result['ok']);
}
public function testSaveTechSchemaSlugifiesKeysBumpsVersionAndKeepsSections(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(['id' => 1, 'version' => 3]);
$capturedJson = null;
$capturedVersion = null;
$repo->method('updateSchema')->willReturnCallback(function (int $t, int $id, string $json, int $version) use (&$capturedJson, &$capturedVersion) {
$capturedJson = $json;
$capturedVersion = $version;
return true;
});
$service = new SecurityCheckTemplateService($repo);
$result = $service->saveTechSchema(self::TENANT_ID, 1, [
['type' => 'section', 'label' => 'Intranet'],
['type' => 'check', 'label' => 'TLS überall erzwungen', 'hint' => 'check certs'],
], 1);
$this->assertTrue($result['ok']);
$this->assertSame(4, $capturedVersion);
$data = json_decode((string) $capturedJson, true);
$this->assertSame(4, $data['version']);
$this->assertSame('section', $data['items'][0]['type']);
$this->assertSame('check', $data['items'][1]['type']);
$this->assertSame('tls_ueberall_erzwungen', $data['items'][1]['key']);
$this->assertSame('check certs', $data['items'][1]['hint']);
}
public function testSaveTechSchemaPersistsMarkdownAndOmitsEmpty(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(['id' => 1, 'version' => 1]);
$capturedJson = null;
$repo->method('updateSchema')->willReturnCallback(function (int $t, int $id, string $json) use (&$capturedJson) {
$capturedJson = $json;
return true;
});
$service = new SecurityCheckTemplateService($repo);
$service->saveTechSchema(self::TENANT_ID, 1, [
['type' => 'check', 'label' => 'TLS', 'markdown' => '**Verify** the certificate chain.'],
['type' => 'check', 'label' => 'Backup', 'markdown' => ' '],
], 1);
$data = json_decode((string) $capturedJson, true);
$this->assertSame('**Verify** the certificate chain.', $data['items'][0]['markdown']);
$this->assertArrayNotHasKey('markdown', $data['items'][1]);
}
public function testSaveTechSchemaDeduplicatesKeys(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(['id' => 1, 'version' => 1]);
$capturedJson = null;
$repo->method('updateSchema')->willReturnCallback(function (int $t, int $id, string $json) use (&$capturedJson) {
$capturedJson = $json;
return true;
});
$service = new SecurityCheckTemplateService($repo);
$service->saveTechSchema(self::TENANT_ID, 1, [
['type' => 'check', 'label' => 'Backup'],
['type' => 'check', 'label' => 'Backup'],
], 1);
$data = json_decode((string) $capturedJson, true);
$this->assertSame('backup', $data['items'][0]['key']);
$this->assertSame('backup_2', $data['items'][1]['key']);
}
public function testSaveTechSchemaRejectsItemWithoutLabel(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(['id' => 1, 'version' => 1]);
$repo->expects($this->never())->method('updateSchema');
$service = new SecurityCheckTemplateService($repo);
$result = $service->saveTechSchema(self::TENANT_ID, 1, [['type' => 'check', 'label' => '']], 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('schema', $result['errors']);
}
public function testSaveTechSchemaRejectsTooManyItems(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->method('findById')->willReturn(['id' => 1, 'version' => 1]);
$items = [];
for ($i = 0; $i <= SecurityCheckTemplateService::MAX_ITEMS; $i++) {
$items[] = ['type' => 'check', 'label' => 'Item ' . $i];
}
$service = new SecurityCheckTemplateService($repo);
$result = $service->saveTechSchema(self::TENANT_ID, 1, $items, 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('schema', $result['errors']);
}
public function testUpdateMetaRejectsEmptyName(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$repo->expects($this->never())->method('updateMeta');
$service = new SecurityCheckTemplateService($repo);
$result = $service->updateMeta(self::TENANT_ID, 1, '', true, 1);
$this->assertFalse($result['ok']);
$this->assertArrayHasKey('product_name', $result['errors']);
}
public function testDecodeSchemaReturnsItems(): void
{
$repo = $this->createMock(SecurityCheckTemplateRepository::class);
$service = new SecurityCheckTemplateService($repo);
$decoded = $service->decodeSchema([
'version' => 5,
'tech_schema_json' => json_encode(['version' => 5, 'items' => [['type' => 'check', 'key' => 'a', 'label' => 'A']]]),
]);
$this->assertSame(5, $decoded['version']);
$this->assertCount(1, $decoded['items']);
}
}