256 lines
8.8 KiB
PHP
256 lines
8.8 KiB
PHP
<?php
|
|
|
|
namespace UbsCsvTransformer\Tests;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use UbsCsvTransformer\ConfigurationLoader;
|
|
|
|
class ConfigurationLoaderTest extends TestCase
|
|
{
|
|
private string $tempFile = '';
|
|
|
|
protected function setUp(): void
|
|
{
|
|
// uniqid gives a unique name; .json extension satisfies the loader's check
|
|
$this->tempFile = sys_get_temp_dir() . '/cfgloader_test_' . uniqid() . '.json';
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
if (file_exists($this->tempFile)) {
|
|
unlink($this->tempFile);
|
|
}
|
|
}
|
|
|
|
private function writeJson(array $data): void
|
|
{
|
|
file_put_contents($this->tempFile, json_encode($data));
|
|
}
|
|
|
|
/**
|
|
* Minimal valid configuration that passes all validation checks.
|
|
*/
|
|
private function validConfig(): array
|
|
{
|
|
return [
|
|
'metadata' => [
|
|
'extractionRules' => [
|
|
['name' => 'account_iban', 'lineNumber' => 1, 'regex' => '(.+)'],
|
|
],
|
|
],
|
|
'csvStructure' => [
|
|
'headerLine' => 1,
|
|
'inputDelimiter' => ';',
|
|
'encoding' => 'UTF-8',
|
|
],
|
|
'columnTransformations' => [
|
|
['sourceColumn' => 'A', 'outputColumn' => 'B', 'type' => 'map'],
|
|
],
|
|
];
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Happy path
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testLoadValidConfigReturnsArray(): void
|
|
{
|
|
$this->writeJson($this->validConfig());
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$config = $loader->load();
|
|
$this->assertIsArray($config);
|
|
$this->assertArrayHasKey('metadata', $config);
|
|
$this->assertArrayHasKey('csvStructure', $config);
|
|
$this->assertArrayHasKey('columnTransformations', $config);
|
|
}
|
|
|
|
public function testGetAllReturnsFullConfig(): void
|
|
{
|
|
$this->writeJson($this->validConfig());
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$loader->load();
|
|
$all = $loader->getAll();
|
|
$this->assertSame(1, $all['csvStructure']['headerLine']);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// get() dot-notation accessor
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testGetDotNotationReturnsValue(): void
|
|
{
|
|
$this->writeJson($this->validConfig());
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$loader->load();
|
|
$this->assertSame(1, $loader->get('csvStructure.headerLine'));
|
|
$this->assertSame(';', $loader->get('csvStructure.inputDelimiter'));
|
|
}
|
|
|
|
public function testGetNonExistentKeyReturnsNull(): void
|
|
{
|
|
$this->writeJson($this->validConfig());
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$loader->load();
|
|
$this->assertNull($loader->get('nonexistent.key'));
|
|
}
|
|
|
|
public function testGetNonExistentKeyReturnsDefault(): void
|
|
{
|
|
$this->writeJson($this->validConfig());
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$loader->load();
|
|
$this->assertSame('fallback', $loader->get('nonexistent', 'fallback'));
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// File not found / bad extension
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testFileNotFoundThrows(): void
|
|
{
|
|
$this->expectException(\RuntimeException::class);
|
|
$loader = new ConfigurationLoader('/nonexistent/path/config.json');
|
|
$loader->load();
|
|
}
|
|
|
|
public function testNonJsonExtensionThrows(): void
|
|
{
|
|
$yamlPath = sys_get_temp_dir() . '/test_config_' . uniqid() . '.yaml';
|
|
file_put_contents($yamlPath, 'key: value');
|
|
try {
|
|
$loader = new ConfigurationLoader($yamlPath);
|
|
$this->expectException(\RuntimeException::class);
|
|
$loader->load();
|
|
} finally {
|
|
if (file_exists($yamlPath)) {
|
|
unlink($yamlPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function testInvalidJsonThrows(): void
|
|
{
|
|
file_put_contents($this->tempFile, '{invalid json content}');
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Required top-level sections
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testMissingMetadataSectionThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
unset($config['metadata']);
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
public function testMissingExtractionRulesThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
unset($config['metadata']['extractionRules']);
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
public function testMissingCsvStructureSectionThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
unset($config['csvStructure']);
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
public function testMissingHeaderLineThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
unset($config['csvStructure']['headerLine']);
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
public function testMissingColumnTransformationsThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
unset($config['columnTransformations']);
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// csvStructure value validation
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testInvalidEncodingThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
$config['csvStructure']['encoding'] = 'LATIN1';
|
|
$this->writeJson($config);
|
|
$this->expectException(\Exception::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
public function testSupportedEncodingsPass(): void
|
|
{
|
|
foreach (['UTF-8', 'ISO-8859-1', 'CP1252'] as $encoding) {
|
|
$config = $this->validConfig();
|
|
$config['csvStructure']['encoding'] = $encoding;
|
|
$this->writeJson($config);
|
|
$loader = new ConfigurationLoader($this->tempFile);
|
|
$result = $loader->load();
|
|
$this->assertSame($encoding, $result['csvStructure']['encoding']);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// directories validation
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testDirectoriesAllKeysPass(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
$config['directories'] = [
|
|
'source' => '/tmp/source',
|
|
'output' => '/tmp/output',
|
|
'archive' => '/tmp/archive',
|
|
'error' => '/tmp/error',
|
|
];
|
|
$this->writeJson($config);
|
|
$result = (new ConfigurationLoader($this->tempFile))->load();
|
|
$this->assertArrayHasKey('directories', $result);
|
|
}
|
|
|
|
public function testDirectoriesMissingSubkeyThrows(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
$config['directories'] = [
|
|
'source' => '/tmp/source',
|
|
'output' => '/tmp/output',
|
|
// 'archive' and 'error' intentionally missing
|
|
];
|
|
$this->writeJson($config);
|
|
$this->expectException(\RuntimeException::class);
|
|
(new ConfigurationLoader($this->tempFile))->load();
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Absent optional 'directories' key does not trigger validation
|
|
// -------------------------------------------------------------------------
|
|
|
|
public function testAbsentDirectoriesKeyDoesNotThrow(): void
|
|
{
|
|
$config = $this->validConfig();
|
|
$this->assertArrayNotHasKey('directories', $config);
|
|
$this->writeJson($config);
|
|
$result = (new ConfigurationLoader($this->tempFile))->load();
|
|
$this->assertArrayNotHasKey('directories', $result);
|
|
}
|
|
}
|