firefly-import-preprocessor/tests/CsvReaderTest.php
Reindl David (IT-PTR-CEN2-SL10) 170b2d2016 release 1.0
2026-05-02 17:53:19 +02:00

200 lines
7.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace UbsCsvTransformer\Tests;
use PHPUnit\Framework\TestCase;
use UbsCsvTransformer\CsvReader;
class CsvReaderTest extends TestCase
{
private string $tempFile = '';
protected function setUp(): void
{
$this->tempFile = tempnam(sys_get_temp_dir(), 'csvreader_test_');
}
protected function tearDown(): void
{
if (file_exists($this->tempFile)) {
unlink($this->tempFile);
}
}
private function write(string $content): void
{
file_put_contents($this->tempFile, $content);
}
private function reader(int $headerLine = 1, string $delimiter = ';', bool $hasBom = false): CsvReader
{
return new CsvReader(
$this->tempFile,
['inputDelimiter' => $delimiter, 'headerLine' => $headerLine, 'hasBom' => $hasBom]
);
}
// -------------------------------------------------------------------------
// readCsvData basic parsing
// -------------------------------------------------------------------------
public function testReadCsvDataSimple(): void
{
$this->write("Name;Age\nAlice;30\nBob;25\n");
$data = $this->reader()->readCsvData();
$this->assertCount(2, $data);
$this->assertSame('Alice', $data[0]['Name']);
$this->assertSame('30', $data[0]['Age']);
$this->assertSame('Bob', $data[1]['Name']);
}
public function testReadCsvDataTrimsWhitespace(): void
{
$this->write("Name ; Age\n Alice ; 30 \n");
$data = $this->reader()->readCsvData();
$this->assertSame('Alice', $data[0]['Name']);
$this->assertSame('30', $data[0]['Age']);
}
// -------------------------------------------------------------------------
// headerLine offset
// -------------------------------------------------------------------------
public function testHeaderLineOffset(): void
{
// Lines 1+2 are metadata, header is line 3
$this->write("Meta1\nMeta2\nColA;ColB\nval1;val2\n");
$data = $this->reader(3)->readCsvData();
$this->assertCount(1, $data);
$this->assertSame('val1', $data[0]['ColA']);
$this->assertSame('val2', $data[0]['ColB']);
}
// -------------------------------------------------------------------------
// readMetadataLines
// -------------------------------------------------------------------------
public function testReadMetadataLines(): void
{
$this->write("Line1\nLine2\nHeader;Col\nData;Row\n");
$meta = $this->reader(3)->readMetadataLines();
$this->assertCount(2, $meta);
$this->assertSame('Line1', $meta[0]);
$this->assertSame('Line2', $meta[1]);
}
public function testReadMetadataLinesHeaderOnLine1IsEmpty(): void
{
$this->write("Name;Age\nAlice;30\n");
$meta = $this->reader(1)->readMetadataLines();
$this->assertSame([], $meta);
}
public function testReadMetadataLinesHeaderOnLine2ReturnsOneLine(): void
{
$this->write("MetaInfo\nName;Age\nAlice;30\n");
$meta = $this->reader(2)->readMetadataLines();
$this->assertCount(1, $meta);
$this->assertSame('MetaInfo', $meta[0]);
}
// -------------------------------------------------------------------------
// maxDataRows limit
// -------------------------------------------------------------------------
public function testMaxDataRowsLimit(): void
{
$this->write("Name;Age\nAlice;30\nBob;25\nCarol;20\n");
$data = $this->reader()->readCsvData(2);
$this->assertCount(2, $data);
$this->assertSame('Alice', $data[0]['Name']);
$this->assertSame('Bob', $data[1]['Name']);
}
public function testMaxDataRowsZeroMeansAll(): void
{
$this->write("Name;Age\nAlice;30\nBob;25\nCarol;20\n");
$data = $this->reader()->readCsvData(0);
$this->assertCount(3, $data);
}
// -------------------------------------------------------------------------
// Empty line skipping
// -------------------------------------------------------------------------
public function testEmptyLinesAreSkipped(): void
{
$this->write("Name;Age\nAlice;30\n\nBob;25\n\n");
$data = $this->reader()->readCsvData();
$this->assertCount(2, $data);
}
// -------------------------------------------------------------------------
// BOM removal
// -------------------------------------------------------------------------
public function testBomIsRemovedFromFirstColumnName(): void
{
// UTF-8 BOM followed immediately by the header
$this->write("\xEF\xBB\xBFName;Age\nAlice;30\n");
$data = $this->reader(1, ';', true)->readCsvData();
$this->assertCount(1, $data);
// The column must be 'Name', not the BOM-prefixed version
$this->assertArrayHasKey('Name', $data[0]);
$this->assertSame('Alice', $data[0]['Name']);
}
public function testNoBomFlagLeavesHeaderIntact(): void
{
// If hasBom is false, BOM bytes stay and the key will be mangled — we only
// assert that the clean path (hasBom=true) works, tested above.
// Here we just verify normal CSV without BOM also works when hasBom=false.
$this->write("Name;Age\nAlice;30\n");
$data = $this->reader(1, ';', false)->readCsvData();
$this->assertArrayHasKey('Name', $data[0]);
}
// -------------------------------------------------------------------------
// getHeaders
// -------------------------------------------------------------------------
public function testGetHeaders(): void
{
$this->write("Col1;Col2;Col3\nA;B;C\n");
$headers = $this->reader()->getHeaders();
$this->assertSame(['Col1', 'Col2', 'Col3'], $headers);
}
// -------------------------------------------------------------------------
// Row with fewer columns than headers
// -------------------------------------------------------------------------
public function testShortRowPaddedWithEmpty(): void
{
$this->write("A;B;C\n1;2\n");
$data = $this->reader()->readCsvData();
$this->assertCount(1, $data);
$this->assertSame('1', $data[0]['A']);
$this->assertSame('2', $data[0]['B']);
$this->assertSame('', $data[0]['C']);
}
// -------------------------------------------------------------------------
// Error cases
// -------------------------------------------------------------------------
public function testFileNotFoundThrowsRuntimeException(): void
{
$this->expectException(\RuntimeException::class);
$reader = new CsvReader('/nonexistent/path/file.csv', ['inputDelimiter' => ';', 'headerLine' => 1]);
$reader->readLines();
}
public function testHeaderLineBeyondFileLengthThrows(): void
{
$this->write("Name;Age\nAlice;30\n");
$this->expectException(\RuntimeException::class);
$this->reader(99)->readCsvData();
}
}