WIP: Sicherheitsnetz vor Phase-1-R\u00fcckbau
Enth\u00e4lt gemischt: Laravel-10-Upgrade + Phase 1 (Contacts-Modul, Duplicats-Commands, Soft-Delete+Merge-Fields) + Phase 2 Code-Umstellungen (inquiry_id, $table='contacts'/'inquiries') + Offers-Modul (Migrationen, Models, offer_id in Booking, offer-Disk in filesystems.php). Phase 2 + Offers werden im folgenden Commit nach dev/backups/phase2-offers-2026-04-17/ verschoben, damit der Workspace auf Phase-1-only (= Test-System-Stand) reduziert ist und direkt auf Live deploybar wird. Tarball-Backup zus\u00e4tzlich unter: ../backups-safety/workspace-pre-phase1-rollback-2026-04-17.tar.gz Made-with: Cursor
This commit is contained in:
parent
389d5d1820
commit
e3dc1afd8e
165 changed files with 21914 additions and 3516 deletions
183
tests/Unit/Services/UtilTest.php
Normal file
183
tests/Unit/Services/UtilTest.php
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Services\Util;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UtilTest extends TestCase
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// _format_number
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testFormatNumberStripsNonNumericCharacters(): void
|
||||
{
|
||||
$this->assertSame('1234,56', Util::_format_number('1.234,56 €'));
|
||||
$this->assertSame('1234,56', Util::_format_number('EUR 1.234,56'));
|
||||
$this->assertSame('100', Util::_format_number('100'));
|
||||
}
|
||||
|
||||
public function testFormatNumberReturnsEmptyStringForNonNumericInput(): void
|
||||
{
|
||||
$this->assertSame('', Util::_format_number('abc'));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// _number_format
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testNumberFormatFormatsWithGermanLocale(): void
|
||||
{
|
||||
$this->assertSame('1.234,56', Util::_number_format(1234.56));
|
||||
$this->assertSame('0,00', Util::_number_format(0));
|
||||
$this->assertSame('1.000,00', Util::_number_format(1000));
|
||||
}
|
||||
|
||||
public function testNumberFormatRespectsCustomDecimalPlaces(): void
|
||||
{
|
||||
$this->assertSame('1.234,5600', Util::_number_format(1234.56, 4));
|
||||
$this->assertSame('1.235', Util::_number_format(1234.56, 0));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// _clean_float
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testCleanFloatHandlesGermanCommaFormat(): void
|
||||
{
|
||||
$this->assertSame(1234.56, Util::_clean_float('1.234,56'));
|
||||
$this->assertSame(1234.56, Util::_clean_float('1234,56'));
|
||||
}
|
||||
|
||||
public function testCleanFloatHandlesDotDecimalFormat(): void
|
||||
{
|
||||
$this->assertSame(1234.56, Util::_clean_float('1234.56'));
|
||||
}
|
||||
|
||||
public function testCleanFloatHandlesCurrencyStrings(): void
|
||||
{
|
||||
$this->assertSame(99.9, Util::_clean_float('99,90 €'));
|
||||
$this->assertSame(0.0, Util::_clean_float('0'));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// _first_replace
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testFirstReplaceStripsRePrefix(): void
|
||||
{
|
||||
$this->assertSame('Betreff', Util::_first_replace('re: Betreff'));
|
||||
$this->assertSame('Betreff', Util::_first_replace('RE: Betreff'));
|
||||
$this->assertSame('Betreff', Util::_first_replace('Re: re: Betreff'));
|
||||
}
|
||||
|
||||
public function testFirstReplaceDoesNotAlterStringWithoutPrefix(): void
|
||||
{
|
||||
$this->assertSame('Betreff', Util::_first_replace('Betreff'));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// _explodeLines / _implodeLines
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testExplodeLinesOnNewlines(): void
|
||||
{
|
||||
$result = Util::_explodeLines("Zeile1\nZeile2\nZeile3");
|
||||
$this->assertSame(['Zeile1', 'Zeile2', 'Zeile3'], $result);
|
||||
}
|
||||
|
||||
public function testExplodeLinesOnWindowsNewlines(): void
|
||||
{
|
||||
$result = Util::_explodeLines("Zeile1\r\nZeile2");
|
||||
$this->assertSame(['Zeile1', 'Zeile2'], $result);
|
||||
}
|
||||
|
||||
public function testExplodeLinesReturnsFalseForEmptyInput(): void
|
||||
{
|
||||
$this->assertNull(Util::_explodeLines(false));
|
||||
$this->assertNull(Util::_explodeLines(''));
|
||||
}
|
||||
|
||||
public function testImplodeLinesJoinsArray(): void
|
||||
{
|
||||
$this->assertSame("Zeile1\nZeile2", Util::_implodeLines(['Zeile1', 'Zeile2'], "\n"));
|
||||
}
|
||||
|
||||
public function testImplodeLinesPassesThroughNonArray(): void
|
||||
{
|
||||
$this->assertSame('Zeile1', Util::_implodeLines('Zeile1'));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// replacePlaceholders
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testReplacePlaceholdersSubstitutesValues(): void
|
||||
{
|
||||
$template = 'Hallo {{name}}, deine Buchungs-Nr. ist {{booking_id}}.';
|
||||
$result = Util::replacePlaceholders($template, [
|
||||
'name' => 'Max Mustermann',
|
||||
'booking_id' => '12345',
|
||||
]);
|
||||
|
||||
$this->assertSame('Hallo Max Mustermann, deine Buchungs-Nr. ist 12345.', $result);
|
||||
}
|
||||
|
||||
public function testReplacePlaceholdersLeavesUnknownPlaceholdersIntact(): void
|
||||
{
|
||||
$template = 'Hallo {{name}}, {{unknown}}';
|
||||
$result = Util::replacePlaceholders($template, ['name' => 'Max']);
|
||||
|
||||
$this->assertStringContainsString('{{unknown}}', $result);
|
||||
}
|
||||
|
||||
public function testReplacePlaceholdersHandlesEmptyReplacements(): void
|
||||
{
|
||||
$template = 'Kein Platzhalter hier.';
|
||||
$this->assertSame($template, Util::replacePlaceholders($template, []));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// sanitize
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testSanitizeRemovesSpecialCharsAndLowercases(): void
|
||||
{
|
||||
$result = Util::sanitize('Hello World!');
|
||||
$this->assertSame('hello_world', $result);
|
||||
}
|
||||
|
||||
public function testSanitizeRespectsForceUppercase(): void
|
||||
{
|
||||
$result = Util::sanitize('Hello', false);
|
||||
$this->assertSame('Hello', $result);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// getExtensionFromMime
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testGetExtensionFromMimeReturnsKnownExtensions(): void
|
||||
{
|
||||
$this->assertSame('pdf', Util::getExtensionFromMime('application/pdf'));
|
||||
$this->assertSame('jpg', Util::getExtensionFromMime('image/jpeg'));
|
||||
$this->assertSame('png', Util::getExtensionFromMime('image/png'));
|
||||
}
|
||||
|
||||
public function testGetExtensionFromMimeReturnsEmptyStringForUnknown(): void
|
||||
{
|
||||
$this->assertSame('', Util::getExtensionFromMime('application/unknown'));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// _formatBytes
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function testFormatBytesFormatsCorrectly(): void
|
||||
{
|
||||
$this->assertSame('1 KB', Util::_formatBytes(1024));
|
||||
$this->assertSame('1 MB', Util::_formatBytes(1024 * 1024));
|
||||
$this->assertSame('0', Util::_formatBytes(0));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue