planRepo = new FakePlanRepository(); $this->userRepo = new FakeUserRepository(); $this->textRepo = new FakeTextRepository(); $this->nodeRepo = new FakeNodeRepository(); $this->scheduledNodeRepo = new FakeScheduledNodeRepository(); $this->user = $this->userRepo->create(new CreateUserDto( email: new EmailAddress('test@test.com'), passwordHash: '', isAdmin: false, )); $text = $this->textRepo->create(new CreateTextDto( name: 'testname', user: $this->user, )); $this->nodeRepo->create(new CreateNodeDto( text: $text, title: 'Root Node', parentNode: null, )); $createScheduledNode = new CreateScheduledNode( scheduledNodeRepo: $this->scheduledNodeRepo, planRepo: $this->planRepo, nodeRepo: $this->nodeRepo, ); $this->createPlan = new CreatePlan( $this->planRepo, $this->userRepo, $this->textRepo, $this->nodeRepo, $createScheduledNode, ); $this->controller = new PlanController(); } private function makeRequest(array $data): ServerRequestInterface { $body = new StreamFactory()->createStream(json_encode($data)); return new ServerRequestFactory() ->createServerRequest('POST', 'http://localhost/api/plans') ->withHeader('Content-Type', 'application/json') ->withAttribute('user', $this->user) ->withBody($body); } public function test_create_plan_returns_201_with_id_and_name(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'My Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(201, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('id', $body); $this->assertEquals('My Plan', $body['name']); } public function test_create_plan_returns_401_when_no_user(): void { $requestWithoutUser = new ServerRequestFactory() ->createServerRequest('POST', 'http://localhost/api/plans') ->withHeader('Content-Type', 'application/json') ->withBody( new StreamFactory()->createStream(json_encode([ 'textId' => 0, 'name' => 'My Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ])) ); $response = $this->controller->createPlan( $requestWithoutUser, new Response(), $this->createPlan, ); $this->assertEquals(401, $response->getStatusCode()); } public function test_create_plan_returns_400_when_text_id_missing(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'name' => 'My Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(400, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_returns_400_when_name_missing(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(400, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_returns_400_when_date_start_missing(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'My Plan', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(400, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_returns_400_when_date_end_missing(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'My Plan', 'dateStart' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(400, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_returns_400_when_date_end_before_start(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'My Plan', 'dateStart' => '2025-01-02', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(400, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_returns_404_when_text_not_found(): void { $response = $this->controller->createPlan( $this->makeRequest([ 'textId' => 99, 'name' => 'My Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals(404, $response->getStatusCode()); $body = json_decode($response->getBody(), true); $this->assertArrayHasKey('error', $body); } public function test_create_plan_persists_plan_in_repository(): void { $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'Persistent Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $storedPlan = $this->planRepo->find(0); $this->assertNotNull($storedPlan); $this->assertEquals('Persistent Plan', $storedPlan->getName()); } public function test_create_plan_schedules_nodes(): void { $this->controller->createPlan( $this->makeRequest([ 'textId' => 0, 'name' => 'Scheduling Plan', 'dateStart' => '2025-01-01', 'dateEnd' => '2025-01-01', ]), new Response(), $this->createPlan, ); $this->assertEquals( 1, $this->scheduledNodeRepo->getNumberOfTimesCreateCalled() ); $this->assertNotNull($this->scheduledNodeRepo->find(0)); } }