builder = new SeasonChecklistBuilder($this->createMock(SeasonTaskDeadlineResolver::class)); } public function testItIsOpenWhileAnEntryRequiringAReturnIsOpen(): void { $seasonAssignment = $this->assignmentWithAllTasks(); $this->assertSame(SeasonChecklistStatus::OPEN, $this->builder->status($seasonAssignment)); } public function testItIsOpenWhenOnlyOfficeInternalEntriesAreDone(): void { $seasonAssignment = $this->assignmentWithAllTasks(); $this->markDone($seasonAssignment, static fn (SeasonTask $task): bool => false === $task->requiresReturn()); $this->assertSame(SeasonChecklistStatus::OPEN, $this->builder->status($seasonAssignment)); } public function testReturnsAreCompleteWhileAnOfficeInternalEntryIsOpen(): void { $seasonAssignment = $this->assignmentWithAllTasks(); $this->markDone($seasonAssignment, static fn (SeasonTask $task): bool => $task->requiresReturn()); $this->assertSame(SeasonChecklistStatus::RETURNS_COMPLETE, $this->builder->status($seasonAssignment)); } public function testItIsCompleteOnceEveryEntryIsDone(): void { $seasonAssignment = $this->assignmentWithAllTasks(); $this->markDone($seasonAssignment, static fn (SeasonTask $task): bool => true); $this->assertSame(SeasonChecklistStatus::COMPLETE, $this->builder->status($seasonAssignment)); } /** * A row of an entry that was removed from the enum would otherwise keep the assignment * unfinished forever, so it is skipped here just like everywhere else. */ public function testItIgnoresRowsWhoseEntryNoLongerExists(): void { $seasonAssignment = $this->assignmentWithAllTasks(); $this->markDone($seasonAssignment, static fn (SeasonTask $task): bool => true); $seasonAssignment->addTask((new SeasonAssignmentTask())->setTaskKey('removed_entry')); $this->assertSame(SeasonChecklistStatus::COMPLETE, $this->builder->status($seasonAssignment)); } private function assignmentWithAllTasks(): SeasonAssignment { $seasonAssignment = new SeasonAssignment(); foreach (SeasonTask::cases() as $case) { $seasonAssignment->addTask((new SeasonAssignmentTask())->setTaskKey($case->value)); } return $seasonAssignment; } /** * @param callable(SeasonTask): bool $matches */ private function markDone(SeasonAssignment $seasonAssignment, callable $matches): void { foreach ($seasonAssignment->getTasks() as $task) { if (null !== $definition = $task->getTask()) { $task->setDone($matches($definition)); } } } }