Import of W&K seminar exports with preview, booking form via form generator with event-dependent field rules, notification routing, inbox with folders and CSV export for W&K. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
134 lines
5.5 KiB
PHP
134 lines
5.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Mummert\ContaoWkSyncBundle\Tests\Import;
|
|
|
|
use Mummert\ContaoWkSyncBundle\Import\ImportMessage;
|
|
use Mummert\ContaoWkSyncBundle\Import\RowMapper;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class RowMapperTest extends TestCase
|
|
{
|
|
/**
|
|
* @param array<string, string> $overrides
|
|
*
|
|
* @return array<string, string>
|
|
*/
|
|
private function row(array $overrides = []): array
|
|
{
|
|
return [
|
|
'kbnr' => '0003259',
|
|
'kbtitel' => 'Pause für den Kopf',
|
|
'kbanreise' => '29.09.2026',
|
|
'kbabreise' => '30.09.2026',
|
|
'kbuanreise' => '09.00',
|
|
'kbuabreise' => '16.00',
|
|
'kbstatus1' => '2',
|
|
'kbsgebiet' => 'Alle Schularten',
|
|
'kbvsnr' => 'EXTP00557',
|
|
'kbvort' => 'TPI Moritzburg',
|
|
'kbkp1' => '240,00',
|
|
'kbkp2' => '1.250,50',
|
|
'kbanzmax' => '20',
|
|
'kbanztat' => '6',
|
|
'kbkdemail' => 'info@example.org',
|
|
'kbkln1' => 'Tobias Richter',
|
|
'kbmref' => "Johanna Fabel\nN.N.\nUwe Hahn\nJohanna Fabel",
|
|
'kbwmemo' => 'Lehrkräfte, alle Schularten, Lehrkräfte',
|
|
'kbpmemo' => "Absatz eins\nZeile zwei\n\nAbsatz zwei",
|
|
'kbzusatz' => "- Punkt 1\n- Punkt 2",
|
|
'kbvsart' => '2',
|
|
...$overrides,
|
|
];
|
|
}
|
|
|
|
public function testMapsAValidRow(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(), 2);
|
|
|
|
self::assertFalse($mapped->skipped);
|
|
self::assertSame('0003259', $mapped->wkId);
|
|
self::assertSame('Pause für den Kopf', $mapped->data['title']);
|
|
self::assertSame(mktime(0, 0, 0, 9, 29, 2026), $mapped->data['startDate']);
|
|
self::assertSame(mktime(0, 0, 0, 9, 30, 2026), $mapped->data['endDate']);
|
|
self::assertTrue($mapped->data['addTime']);
|
|
self::assertSame(mktime(9, 0, 0, 9, 29, 2026), $mapped->data['startTime']);
|
|
self::assertSame(mktime(16, 0, 0, 9, 30, 2026), $mapped->data['endTime']);
|
|
self::assertSame('2', $mapped->data['wkState']);
|
|
self::assertSame('EXTP00557', $mapped->data['wkInternalEventNumber']);
|
|
self::assertSame(240.0, $mapped->data['wkPrice1']);
|
|
self::assertSame(1250.5, $mapped->data['wkPrice2']);
|
|
self::assertSame(20, $mapped->data['wkMaxPlaces']);
|
|
self::assertSame(14, $mapped->data['wkPlacesLeft']);
|
|
self::assertSame('Tobias Richter', $mapped->instructorName);
|
|
self::assertSame(['Johanna Fabel', 'Uwe Hahn'], $mapped->speakerNames);
|
|
self::assertSame('Lehrkräfte, alle Schularten', $mapped->data['wkTags']);
|
|
self::assertSame('<p>Absatz eins<br>Zeile zwei</p>'."\n".'<p>Absatz zwei</p>', $mapped->data['teaser']);
|
|
self::assertSame('<ul><li>Punkt 1</li><li>Punkt 2</li></ul>', $mapped->data['wkTopics']);
|
|
self::assertSame('Alle Schularten', $mapped->categoryText);
|
|
self::assertSame(2, $mapped->data['wkEventType']);
|
|
self::assertSame([], $mapped->messages);
|
|
}
|
|
|
|
public function testAllDayEventGetsMidnightAndEndOfDay(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(['kbuanreise' => '', 'kbuabreise' => '']), 2);
|
|
|
|
self::assertFalse($mapped->data['addTime']);
|
|
self::assertSame(mktime(0, 0, 0, 9, 29, 2026), $mapped->data['startTime']);
|
|
self::assertSame(mktime(0, 0, 0, 10, 1, 2026) - 1, $mapped->data['endTime']);
|
|
}
|
|
|
|
public function testSkipsRowsWithoutLeadingZeroOrInternalNumberOrTitle(): void
|
|
{
|
|
$mapper = new RowMapper();
|
|
|
|
self::assertTrue($mapper->map($this->row(['kbnr' => '3259']), 2)->skipped);
|
|
self::assertTrue($mapper->map($this->row(['kbvsnr' => '']), 2)->skipped);
|
|
self::assertTrue($mapper->map($this->row(['kbtitel' => '']), 2)->skipped);
|
|
self::assertTrue($mapper->map($this->row(['kbanreise' => '. .']), 2)->skipped);
|
|
}
|
|
|
|
public function testKeineBecomesEmptyInternalNumberCaseInsensitive(): void
|
|
{
|
|
$mapper = new RowMapper();
|
|
|
|
self::assertSame('', $mapper->map($this->row(['kbvsnr' => 'Keine']), 2)->data['wkInternalEventNumber']);
|
|
self::assertSame('', $mapper->map($this->row(['kbvsnr' => 'keine']), 2)->data['wkInternalEventNumber']);
|
|
}
|
|
|
|
public function testInvalidEmailBecomesWarningAndEmptyField(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(['kbkdemail' => 'kaputt']), 2);
|
|
|
|
self::assertSame('', $mapped->data['wkOrganizerEmail']);
|
|
self::assertCount(1, $mapped->messages);
|
|
self::assertSame(ImportMessage::WARNING, $mapped->messages[0]->type);
|
|
}
|
|
|
|
public function testExternalRegistrationUrlIsKept(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(['kbkdemail' => 'https://example.org/anmeldung?x=1']), 2);
|
|
|
|
self::assertSame('https://example.org/anmeldung?x=1', $mapped->data['wkOrganizerEmail']);
|
|
self::assertSame([], $mapped->messages);
|
|
}
|
|
|
|
public function testEndDateBeforeStartFallsBackToStart(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(['kbabreise' => '01.01.2020']), 2);
|
|
|
|
self::assertSame($mapped->data['startDate'], $mapped->data['endDate']);
|
|
self::assertSame(ImportMessage::WARNING, $mapped->messages[0]->type);
|
|
}
|
|
|
|
public function testStreetAndCountryAreMappedCorrectly(): void
|
|
{
|
|
$mapped = (new RowMapper())->map($this->row(['kbkdstr' => 'Bahnhofstraße 9', 'kbkdlkz' => 'D']), 2);
|
|
|
|
self::assertSame('Bahnhofstraße 9', $mapped->data['wkOrganizerStreet']);
|
|
self::assertSame('D', $mapped->data['wkOrganizerCountryCode']);
|
|
}
|
|
}
|