|
@@ -30,7 +30,7 @@ final class SprintWeekRepositoryTest extends TestCase
|
|
|
$weeks = new SprintWeekRepository($pdo);
|
|
$weeks = new SprintWeekRepository($pdo);
|
|
|
|
|
|
|
|
$sprint = $sprints->create('S', '2026-01-05', '2026-01-30', 0.2);
|
|
$sprint = $sprints->create('S', '2026-01-05', '2026-01-30', 0.2);
|
|
|
- $sprints->materializeWeeks($sprint->id, '2026-01-05', 4);
|
|
|
|
|
|
|
+ $sprints->materializeWeeks($sprint->id, '2026-01-05', '2026-01-30', 4);
|
|
|
|
|
|
|
|
return [$sprints, $weeks, $sprint->id];
|
|
return [$sprints, $weeks, $sprint->id];
|
|
|
}
|
|
}
|
|
@@ -47,6 +47,66 @@ final class SprintWeekRepositoryTest extends TestCase
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function testMaterializeWeeksTrimsTrailingWeekToSprintEnd(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $pdo = $this->makeDb();
|
|
|
|
|
+ $sprints = new SprintRepository($pdo);
|
|
|
|
|
+ $weeks = new SprintWeekRepository($pdo);
|
|
|
|
|
+
|
|
|
|
|
+ // Mon 2026-01-05 → Wed 2026-01-14 → 2 weeks; the trailing week stops on Wed.
|
|
|
|
|
+ $sprint = $sprints->create('S', '2026-01-05', '2026-01-14', 0.2);
|
|
|
|
|
+ $sprints->materializeWeeks($sprint->id, '2026-01-05', '2026-01-14', 2);
|
|
|
|
|
+
|
|
|
|
|
+ $rows = $weeks->allForSprint($sprint->id);
|
|
|
|
|
+ $this->assertCount(2, $rows);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertSame(SprintWeek::MASK_ALL, $rows[0]->activeDaysMask);
|
|
|
|
|
+ $this->assertSame(5.0, $rows[0]->maxWorkingDays);
|
|
|
|
|
+
|
|
|
|
|
+ // Mo + Di + Mi = bit0|bit1|bit2 = 7, three workdays.
|
|
|
|
|
+ $this->assertSame(0b00111, $rows[1]->activeDaysMask);
|
|
|
|
|
+ $this->assertSame(3.0, $rows[1]->maxWorkingDays);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function testMaterializeWeeksTrimsLeadingPartialWeekFromMidWeekStart(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $pdo = $this->makeDb();
|
|
|
|
|
+ $sprints = new SprintRepository($pdo);
|
|
|
|
|
+ $weeks = new SprintWeekRepository($pdo);
|
|
|
|
|
+
|
|
|
|
|
+ // Sprint runs Wed 2026-01-07 → Fri 2026-01-23 (3 weeks).
|
|
|
|
|
+ $sprint = $sprints->create('S', '2026-01-07', '2026-01-23', 0.2);
|
|
|
|
|
+ $sprints->materializeWeeks($sprint->id, '2026-01-07', '2026-01-23', 3);
|
|
|
|
|
+
|
|
|
|
|
+ $rows = $weeks->allForSprint($sprint->id);
|
|
|
|
|
+ $this->assertCount(3, $rows);
|
|
|
|
|
+
|
|
|
|
|
+ // W1: Wed–Tue spans all five Mo..Fr weekdays inside the sprint.
|
|
|
|
|
+ $this->assertSame(SprintWeek::MASK_ALL, $rows[0]->activeDaysMask);
|
|
|
|
|
+ // W2: same, fully interior.
|
|
|
|
|
+ $this->assertSame(SprintWeek::MASK_ALL, $rows[1]->activeDaysMask);
|
|
|
|
|
+ // W3 starts Wed Jan 21 — only Wed/Thu/Fri fall inside [start, end].
|
|
|
|
|
+ // Mi + Do + Fr = bit2|bit3|bit4 = 28.
|
|
|
|
|
+ $this->assertSame(0b11100, $rows[2]->activeDaysMask);
|
|
|
|
|
+ $this->assertSame(3.0, $rows[2]->maxWorkingDays);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function testMaterializeWeeksWeekendOnlySpanProducesEmptyMask(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $pdo = $this->makeDb();
|
|
|
|
|
+ $sprints = new SprintRepository($pdo);
|
|
|
|
|
+ $weeks = new SprintWeekRepository($pdo);
|
|
|
|
|
+
|
|
|
|
|
+ // Single-day sprint on Sat 2026-01-10 → no weekdays in range.
|
|
|
|
|
+ $sprint = $sprints->create('S', '2026-01-10', '2026-01-10', 0.2);
|
|
|
|
|
+ $sprints->materializeWeeks($sprint->id, '2026-01-10', '2026-01-10', 1);
|
|
|
|
|
+
|
|
|
|
|
+ $rows = $weeks->allForSprint($sprint->id);
|
|
|
|
|
+ $this->assertCount(1, $rows);
|
|
|
|
|
+ $this->assertSame(0, $rows[0]->activeDaysMask);
|
|
|
|
|
+ $this->assertSame(0.0, $rows[0]->maxWorkingDays);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function testUpdateActiveDaysWritesBothColumns(): void
|
|
public function testUpdateActiveDaysWritesBothColumns(): void
|
|
|
{
|
|
{
|
|
|
[, $weeks, $sprintId] = $this->seedSprint();
|
|
[, $weeks, $sprintId] = $this->seedSprint();
|