Files
myep-team/tests/Model/WorkMonthDaysTest.php
T

145 lines
5.4 KiB
PHP

<?php
namespace App\Tests\Model;
use App\Model\WorkMonthDays;
use App\Saas\Model\TimeAccount;
use App\Saas\Model\TimeAccountDay;
use PHPUnit\Framework\TestCase;
class WorkMonthDaysTest extends TestCase
{
public function testItRoundTripsThroughTheStoredShape(): void
{
$stored = [
'2026-03-01' => ['minutes' => 285],
'2026-03-05' => ['minutes' => 0, 'absence' => 'Ruhetag 24/25'],
];
$this->assertSame($stored, WorkMonthDays::fromArray($stored)->toArray());
}
public function testItSortsAndDropsEntriesItCannotRead(): void
{
$days = WorkMonthDays::fromArray([
'2026-03-05' => ['minutes' => 60],
'not-a-date' => ['minutes' => 120],
'2026-03-01' => ['minutes' => 30, 'absence' => ''],
'2026-03-09' => 'not an entry',
]);
$this->assertSame(['2026-03-01', '2026-03-05'], array_keys($days->toArray()));
$this->assertArrayNotHasKey('absence', $days->toArray()['2026-03-01'], 'An empty label is no label.');
}
public function testAMissingMinutesKeyCountsAsZero(): void
{
$days = WorkMonthDays::fromArray(['2026-03-01' => ['absence' => 'Ferien']]);
$this->assertSame(0, $days->getTotalMinutes());
$this->assertSame(1, $days->countAbsenceDays());
$this->assertSame(0, $days->countWorkedDays());
}
public function testItSummarisesTheMonth(): void
{
$days = WorkMonthDays::fromArray([
'2026-03-01' => ['minutes' => 285],
'2026-03-05' => ['minutes' => 0, 'absence' => 'Ruhetag 24/25'],
'2026-03-06' => ['minutes' => 600],
]);
$this->assertSame(885, $days->getTotalMinutes());
$this->assertSame(2, $days->countWorkedDays());
$this->assertSame(1, $days->countAbsenceDays());
}
public function testItBuildsFromATimeAccount(): void
{
$account = new TimeAccount('e-1', 2026, 3, 345, 9900, 'Operations', [
'2026-03-01' => new TimeAccountDay(new \DateTimeImmutable('2026-03-01'), 285, null, '09:00', '14:45', 60),
'2026-03-05' => new TimeAccountDay(new \DateTimeImmutable('2026-03-05'), 60, 'Ferien'),
], []);
$this->assertSame([
'2026-03-01' => ['minutes' => 285, 'break' => 60, 'start' => '09:00', 'end' => '14:45'],
'2026-03-05' => ['minutes' => 60, 'absence' => 'Ferien'],
], WorkMonthDays::fromTimeAccount($account)->toArray());
}
public function testASpanNeedsBothEnds(): void
{
$days = WorkMonthDays::fromArray([
'2026-03-01' => ['minutes' => 60, 'start' => '09:00'],
'2026-03-02' => ['minutes' => 60, 'start' => '09:00', 'end' => 'noon'],
'2026-03-03' => ['minutes' => 60, 'start' => '09:00', 'end' => '10:00'],
])->forCalendarMonth(2026, 3);
$this->assertFalse($days[0]->hasSpan());
$this->assertFalse($days[1]->hasSpan());
$this->assertTrue($days[2]->hasSpan());
}
public function testItTotalsTheBreaks(): void
{
$days = WorkMonthDays::fromArray([
'2026-03-01' => ['minutes' => 285, 'break' => 60],
'2026-03-02' => ['minutes' => 405, 'break' => 150],
'2026-03-03' => ['minutes' => 180],
]);
$this->assertSame(210, $days->getTotalBreakMinutes());
$this->assertSame(0, $days->forCalendarMonth(2026, 3)[2]->getBreakMinutes());
}
/**
* The calendar, not the payload, decides how many rows a month has: days the SaaS never
* reported still need a line in the table and in the PDF.
*/
public function testItFillsEveryCalendarDayOfALongMonth(): void
{
$days = WorkMonthDays::fromArray(['2026-03-05' => ['minutes' => 0, 'absence' => 'Ruhetag 24/25']]);
$calendar = $days->forCalendarMonth(2026, 3);
$this->assertCount(31, $calendar);
$this->assertSame('2026-03-01', $calendar[0]->getDate()->format('Y-m-d'));
$this->assertSame('2026-03-31', $calendar[30]->getDate()->format('Y-m-d'));
}
public function testItFillsEveryCalendarDayOfAShortMonth(): void
{
$this->assertCount(28, WorkMonthDays::fromArray([])->forCalendarMonth(2026, 2));
$this->assertCount(29, WorkMonthDays::fromArray([])->forCalendarMonth(2024, 2));
}
/**
* "Not reported" and "reported as zero" are different things: a rest day is a real
* booking of nothing, an unreported day is a gap.
*/
public function testItSeparatesUnreportedDaysFromZeroDays(): void
{
$calendar = WorkMonthDays::fromArray([
'2026-03-05' => ['minutes' => 0, 'absence' => 'Ruhetag 24/25'],
])->forCalendarMonth(2026, 3);
$restDay = $calendar[4];
$this->assertSame('2026-03-05', $restDay->getDate()->format('Y-m-d'));
$this->assertTrue($restDay->isReported());
$this->assertSame(0, $restDay->getMinutes());
$this->assertSame('Ruhetag 24/25', $restDay->getAbsence());
$gap = $calendar[0];
$this->assertFalse($gap->isReported());
$this->assertNull($gap->getMinutes());
$this->assertFalse($gap->isAbsence());
}
public function testItKnowsWeekends(): void
{
$calendar = WorkMonthDays::fromArray([])->forCalendarMonth(2026, 3);
$this->assertTrue($calendar[0]->isWeekend(), '1 March 2026 is a Sunday.');
$this->assertFalse($calendar[1]->isWeekend());
}
}