release 1.0
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user