| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- <?php
- /*
- * Copyright 2026 Alessandro Chiapparini <sprint_planer_web@chiapparini.org>
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * See the LICENSE file in the project root for the full license text.
- */
- declare(strict_types=1);
- namespace App\Tests\Repositories;
- use App\Domain\SprintWeek;
- use App\Repositories\SprintRepository;
- use App\Repositories\SprintWeekRepository;
- use App\Tests\TestCase;
- /**
- * Phase 12: per-week weekday selection drives Arbeitstage.
- */
- final class SprintWeekRepositoryTest extends TestCase
- {
- /** @return array{SprintRepository, SprintWeekRepository, int} */
- private function seedSprint(): array
- {
- $pdo = $this->makeDb();
- $sprints = new SprintRepository($pdo);
- $weeks = new SprintWeekRepository($pdo);
- $sprint = $sprints->create('S', '2026-01-05', '2026-01-30', 0.2);
- $sprints->materializeWeeks($sprint->id, '2026-01-05', 4);
- return [$sprints, $weeks, $sprint->id];
- }
- public function testMaterializeWeeksDefaultsToAllFiveDays(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $rows = $weeks->allForSprint($sprintId);
- $this->assertCount(4, $rows);
- foreach ($rows as $w) {
- $this->assertSame(SprintWeek::MASK_ALL, $w->activeDaysMask);
- $this->assertSame(5.0, $w->maxWorkingDays);
- }
- }
- public function testUpdateActiveDaysWritesBothColumns(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $first = $weeks->allForSprint($sprintId)[0];
- $result = $weeks->updateActiveDays($first->id, 0b01111); // drop Fr
- $this->assertSame(SprintWeek::MASK_ALL, $result['before']->activeDaysMask);
- $this->assertSame(0b01111, $result['after']->activeDaysMask);
- $this->assertSame(4.0, $result['after']->maxWorkingDays);
- // Second query hydrates the same row from disk.
- $reloaded = $weeks->find($first->id);
- $this->assertNotNull($reloaded);
- $this->assertSame(0b01111, $reloaded->activeDaysMask);
- $this->assertSame(4.0, $reloaded->maxWorkingDays);
- }
- public function testUpdateActiveDaysClampsBitsOutsideMoFr(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $first = $weeks->allForSprint($sprintId)[0];
- $result = $weeks->updateActiveDays($first->id, 0xFF);
- $this->assertSame(SprintWeek::MASK_ALL, $result['after']->activeDaysMask);
- $this->assertSame(5.0, $result['after']->maxWorkingDays);
- }
- public function testUpdateActiveDaysToEmptyMaskZeroesCount(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $first = $weeks->allForSprint($sprintId)[0];
- $result = $weeks->updateActiveDays($first->id, 0);
- $this->assertSame(0, $result['after']->activeDaysMask);
- $this->assertSame(0.0, $result['after']->maxWorkingDays);
- $this->assertSame([], $result['after']->activeDays());
- }
- public function testSyncCountAppendsWeeksWithAllDaysActive(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $diff = $weeks->syncCount($sprintId, '2026-01-05', 6);
- $this->assertCount(2, $diff['added']);
- foreach ($diff['added'] as $w) {
- $this->assertSame(SprintWeek::MASK_ALL, $w->activeDaysMask);
- $this->assertSame(5.0, $w->maxWorkingDays);
- }
- }
- public function testRealignDatesRewritesOffsetsAndPreservesMask(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- // Customise week 2's mask so we can verify it survives realignment.
- $week2 = $weeks->allForSprint($sprintId)[1];
- $weeks->updateActiveDays($week2->id, 0b00111); // Mo Di Mi only
- // Move the sprint start one week forward.
- $diffs = $weeks->realignDates($sprintId, '2026-01-12');
- $this->assertCount(4, $diffs, 'every existing week shifted one week');
- $reloaded = $weeks->allForSprint($sprintId);
- $this->assertSame('2026-01-12', $reloaded[0]->startDate);
- $this->assertSame('2026-01-19', $reloaded[1]->startDate);
- $this->assertSame('2026-01-26', $reloaded[2]->startDate);
- $this->assertSame('2026-02-02', $reloaded[3]->startDate);
- // Mask + maxWorkingDays untouched by realignment.
- $this->assertSame(0b00111, $reloaded[1]->activeDaysMask);
- $this->assertSame(3.0, $reloaded[1]->maxWorkingDays);
- }
- public function testRealignDatesNoOpWhenAlreadyAligned(): void
- {
- [, $weeks, $sprintId] = $this->seedSprint();
- $diffs = $weeks->realignDates($sprintId, '2026-01-05');
- $this->assertSame([], $diffs, 'no UPDATEs when offsets already match');
- }
- }
|