createProject(); $service = new BoardService(); $state = $service->getBoardState($projectId); self::assertSame( ['backlog', 'ready', 'in-progress', 'review', 'done', 'trash'], array_column($state['columns'], 'id') ); self::assertSame([], $state['tasks']); self::assertSame([], $state['notes']); self::assertSame('Demo Project', $state['project']['title']); } /** * Ensure creating a project initializes markdown storage and default board state. * * @return void */ public function testCreateProjectBuildsInitialBoardState(): void { $service = new BoardService(); $state = $service->createProject('Release Planning', 'Track launch work.', 'release-planning'); self::assertSame('release-planning', $state['project']['id']); self::assertSame('Release Planning', $state['project']['title']); self::assertSame('Track launch work.', trim((string) $state['project']['body'])); self::assertSame( ['backlog', 'ready', 'in-progress', 'review', 'done', 'trash'], array_column($state['columns'], 'id') ); self::assertFileExists($this->projectRoot . DIRECTORY_SEPARATOR . 'release-planning' . DIRECTORY_SEPARATOR . 'index.md'); } /** * Ensure a created task is persisted and returned in board state. * * @return void */ public function testCreateTaskPersistsTaskInRequestedColumn(): void { $projectId = $this->createProject(); $service = new BoardService(); $state = $service->createTask($projectId, 'Ship first milestone', 'ready', 'Write release notes'); self::assertSame('Ship first milestone', $state['task']['title']); self::assertSame('ready', $state['task']['column']); self::assertSame('Write release notes', $state['task']['body']); self::assertCount(1, $state['tasks']); self::assertSame($state['task']['id'], $state['tasks'][0]['id']); self::assertNotSame('0', $state['revision']); } /** * Ensure deleting a task without force moves it into trash. * * @return void */ public function testDeleteTaskMovesTaskToTrashByDefault(): void { $projectId = $this->createProject(); $service = new BoardService(); $created = $service->createTask($projectId, 'Clean up copy', 'in-progress'); $state = $service->deleteTask($projectId, $created['task']['id']); self::assertCount(1, $state['tasks']); self::assertSame('trash', $state['tasks'][0]['column']); self::assertSame($created['task']['id'], $state['tasks'][0]['id']); } /** * Ensure removing a column moves its tasks into trash and keeps trash available. * * @return void */ public function testUpdateBoardMovesDeletedColumnTasksIntoTrash(): void { $projectId = $this->createProject(); $service = new BoardService(); $service->createTask($projectId, 'Review architecture', 'review'); $state = $service->updateBoard( $projectId, [ ['id' => 'backlog', 'label' => 'Backlog'], ['id' => 'ready', 'label' => 'Ready'], ['id' => 'in-progress', 'label' => 'In Progress'], ['id' => 'done', 'label' => 'Done'], ['id' => 'trash', 'label' => 'Trash'], ], 'review' ); self::assertContains('trash', array_column($state['columns'], 'id')); self::assertCount(1, $state['tasks']); self::assertSame('trash', $state['tasks'][0]['column']); } }