138 lines
4.9 KiB
PHP
138 lines
4.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Tests\Service\Assignment;
|
|
|
|
use App\Service\Assignment\PickupDepartureOrder;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* The fixtures here are real destination rows, because the shapes that make this hard are
|
|
* not ones anyone would invent: BusProNet mixes dated and bare times in the same row, and
|
|
* the departures run across midnight.
|
|
*/
|
|
class PickupDepartureOrderTest extends TestCase
|
|
{
|
|
public function testBareClockTimesFollowTheDatedEveningDepartures(): void
|
|
{
|
|
// destination PMVUS/090324, in its stored order
|
|
$sorted = PickupDepartureOrder::sort([
|
|
self::pickup(1, 'Hannover', '08.03.2024 20:45:00'),
|
|
self::pickup(2, 'Kassel', '00:30'),
|
|
self::pickup(3, 'Basel', '04:15'),
|
|
self::pickup(4, 'Karlsruhe', '02:45'),
|
|
self::pickup(5, 'Göttingen', '08.03.2024 22:00:00'),
|
|
self::pickup(6, 'Frankfurt', '01:30'),
|
|
self::pickup(7, 'Mannheim', '08.03.2024 23:30:00'),
|
|
]);
|
|
|
|
$this->assertSame(
|
|
['Hannover', 'Göttingen', 'Mannheim', 'Kassel', 'Frankfurt', 'Karlsruhe', 'Basel'],
|
|
array_column($sorted, 'city'),
|
|
);
|
|
}
|
|
|
|
public function testADatedDepartureAfterMidnightKeepsItsOwnDay(): void
|
|
{
|
|
// destination DKIWE/110425: 03:15 carries the next day's date itself, so it must not
|
|
// be pulled back in front of the evening departures
|
|
$sorted = PickupDepartureOrder::sort([
|
|
self::pickup(1, 'Kiel', '02:15'),
|
|
self::pickup(2, 'Hamburg', '10.04.2025 23:59:00'),
|
|
self::pickup(3, 'Flensburg', '10.04.2025 21:30:00'),
|
|
self::pickup(4, 'Lübeck', '10.04.2025 23:00:00'),
|
|
self::pickup(5, 'Bremen', '11.04.2025 03:15:00'),
|
|
self::pickup(6, 'Rostock', '01:00'),
|
|
self::pickup(7, 'Schwerin', '04:15'),
|
|
]);
|
|
|
|
$this->assertSame(
|
|
['Flensburg', 'Lübeck', 'Hamburg', 'Rostock', 'Kiel', 'Bremen', 'Schwerin'],
|
|
array_column($sorted, 'city'),
|
|
);
|
|
}
|
|
|
|
public function testWithoutAnyDatedEntryTheClockAloneOrders(): void
|
|
{
|
|
$sorted = PickupDepartureOrder::sort([
|
|
self::pickup(1, 'Ulm', '07:30'),
|
|
self::pickup(2, 'Augsburg', '05:15'),
|
|
self::pickup(3, 'München', '09:00'),
|
|
]);
|
|
|
|
$this->assertSame(['Augsburg', 'Ulm', 'München'], array_column($sorted, 'city'));
|
|
}
|
|
|
|
public function testAResolvedDatetimeWinsOverTheStoredTime(): void
|
|
{
|
|
// what MyE&P's travel export delivers: time for display, datetime for ordering
|
|
$sorted = PickupDepartureOrder::sort([
|
|
[...self::pickup(1, 'Kassel', '00:30'), 'datetime' => '2024-03-09T00:30:00+01:00'],
|
|
[...self::pickup(2, 'Hannover', '20:45'), 'datetime' => '2024-03-08T20:45:00+01:00'],
|
|
]);
|
|
|
|
$this->assertSame(['Hannover', 'Kassel'], array_column($sorted, 'city'));
|
|
}
|
|
|
|
public function testEntriesWithoutAReadableTimeGoLastInTheirStoredOrder(): void
|
|
{
|
|
$sorted = PickupDepartureOrder::sort([
|
|
self::pickup(1, 'Ohne Zeit', ''),
|
|
self::pickup(2, 'Nur Datum', '16.02.2024'),
|
|
self::pickup(3, 'Bremen', '22:00'),
|
|
self::pickup(4, 'Gar nichts', null),
|
|
]);
|
|
|
|
$this->assertSame(
|
|
['Bremen', 'Ohne Zeit', 'Nur Datum', 'Gar nichts'],
|
|
array_column($sorted, 'city'),
|
|
);
|
|
}
|
|
|
|
public function testTheClockReadsBothStoredTimeShapes(): void
|
|
{
|
|
$this->assertSame('20:45', PickupDepartureOrder::clock(self::pickup(1, 'Hannover', '08.03.2024 20:45:00')));
|
|
$this->assertSame('02:15', PickupDepartureOrder::clock(self::pickup(2, 'Kassel', '02:15')));
|
|
}
|
|
|
|
public function testTheClockIsNullWhenNoTimeCanBeRead(): void
|
|
{
|
|
$this->assertNull(PickupDepartureOrder::clock(self::pickup(1, 'Nur Datum', '16.02.2024')));
|
|
$this->assertNull(PickupDepartureOrder::clock(self::pickup(2, 'Ohne Zeit', '')));
|
|
$this->assertNull(PickupDepartureOrder::clock(self::pickup(3, 'Gar nichts', null)));
|
|
}
|
|
|
|
public function testTheClockPrefersAResolvedDatetime(): void
|
|
{
|
|
$pickup = [...self::pickup(1, 'Hannover', '08.03.2024 20:45:00'), 'datetime' => '2024-03-08T20:45:00+01:00'];
|
|
|
|
$this->assertSame('20:45', PickupDepartureOrder::clock($pickup));
|
|
}
|
|
|
|
public function testAnEmptyListStaysEmpty(): void
|
|
{
|
|
$this->assertSame([], PickupDepartureOrder::sort([]));
|
|
}
|
|
|
|
public function testTheStoredEntriesArePassedThroughUntouched(): void
|
|
{
|
|
$pickups = [self::pickup(7, 'Bremen', '22:00')];
|
|
|
|
$this->assertSame($pickups, PickupDepartureOrder::sort($pickups));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private static function pickup(int $busProId, string $city, ?string $time): array
|
|
{
|
|
return [
|
|
'busProId' => $busProId,
|
|
'city' => $city,
|
|
'street' => 'Irgendwo 1',
|
|
'time' => $time,
|
|
];
|
|
}
|
|
}
|