Goal-Calibration/tests/Unit/Plan/UseCases/CreatePlanTest.php
Yisroel Baum cbbbc80326
update downstream tests for text user requirement
Text now requires a User on construction. seed a user in
each test setUp that creates a Text directly or through the
fake repository so the suite remains green.
2026-05-02 21:27:55 +03:00

329 lines
10 KiB
PHP

<?php
namespace Tests\Unit\Plan\UseCases;
use App\Exceptions\BadRequestException;
use App\Node\CreateNodeDto;
use App\Plan\UseCases\CreatePlan;
use App\Plan\UseCases\CreatePlanRequest;
use App\ScheduledNode\UseCases\CreateScheduledNode;
use App\Text\CreateTextDto;
use App\User\UseCases\CreateUserDto;
use App\User\User;
use App\ValueObjects\EmailAddress;
use DateTimeImmutable;
use DomainException;
use Tests\Fakes\FakeNodeRepository;
use Tests\Fakes\FakePlanRepository;
use PHPUnit\Framework\TestCase;
use Tests\Fakes\FakeScheduledNodeRepository;
use Tests\Fakes\FakeTextRepository;
use Tests\Fakes\FakeUserRepository;
class CreatePlanTest extends TestCase
{
private FakePlanRepository $planRepo;
private FakeUserRepository $userRepo;
private FakeTextRepository $textRepo;
private FakeNodeRepository $nodeRepo;
private FakeScheduledNodeRepository $scheduledNodeRepo;
private CreateScheduledNode $createScheduledNode;
private CreatePlan $useCase;
public function setUp(): void
{
$this->planRepo = new FakePlanRepository();
$this->userRepo = new FakeUserRepository();
$this->textRepo = new FakeTextRepository();
$this->nodeRepo = new FakeNodeRepository();
$this->scheduledNodeRepo = new FakeScheduledNodeRepository();
$user = $this->userRepo->create(new CreateUserDto(
email: new EmailAddress('test@test.com'),
passwordHash: '',
isAdmin: false,
));
$this->createScheduledNode = new CreateScheduledNode(
scheduledNodeRepo: $this->scheduledNodeRepo,
planRepo: $this->planRepo,
nodeRepo: $this->nodeRepo,
);
$this->textRepo->create(new CreateTextDto(
name: 'testname',
user: $user,
));
$this->useCase = new CreatePlan(
$this->planRepo,
$this->userRepo,
$this->textRepo,
$this->nodeRepo,
$this->createScheduledNode,
);
}
public function test_create_plan(): void
{
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
$this->assertEquals('testPlan', $plan->getName());
}
public function test_plan_has_user(): void
{
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
$this->assertInstanceOf(User::class, $plan->getUser());
}
public function test_nonexistant_user_id_throws(): void
{
$this->expectException(DomainException::class);
$this->expectExceptionMessage("User with id: 1 doesnt exist");
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 1,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
}
public function test_nonexistant_text_id_throws(): void
{
$this->expectException(DomainException::class);
$this->expectExceptionMessage("Text with id: 1 doesnt exist");
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 1,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
}
public function test_plan_schedules_nodes_on_creation(): void
{
$text = $this->textRepo->find(0);
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'testtitle',
parentNode: null,
));
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
$this->assertNotNull($this->scheduledNodeRepo->find(0));
}
public function test_plan_only_schedules_nodes_which_arent_parents(): void
{
$text = $this->textRepo->find(0);
$rootNode = $this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'root node',
parentNode: null,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child node',
parentNode: $rootNode,
));
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
$this->assertEquals(
1,
$this->scheduledNodeRepo->getNumberOfTimesCreateCalled()
);
}
public function test_throws_if_user_id_is_null(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('userId is required');
$this->useCase->execute(new CreatePlanRequest(
userId: null,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
}
public function test_throws_if_text_id_is_null(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('textId is required');
$this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: null,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
}
public function test_throws_if_name_is_null(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('name is required');
$this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: null,
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-01',
));
}
public function test_throws_if_date_start_is_null(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('date start is required');
$this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'test',
textId: 0,
dateStart: null,
dateEnd: '2025-01-01',
));
}
public function test_throws_if_date_end_is_null(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('date end is required');
$this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'test',
textId: 0,
dateStart: '2025-01-01',
dateEnd: null,
));
}
public function test_throws_if_date_end_is_before_date_start(): void
{
$this->expectException(BadRequestException::class);
$this->expectExceptionMessage('date end cannot be before date start');
$this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'test',
textId: 0,
dateStart: '2025-01-02',
dateEnd: '2025-01-01',
));
}
public function test_scheduled_nodes_are_scheduled_on_different_days(): void
{
$text = $this->textRepo->find(0);
$rootNode = $this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'root node',
parentNode: null,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child 1',
parentNode: $rootNode,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child 2',
parentNode: $rootNode,
));
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-02',
));
$childOne = $this->scheduledNodeRepo->find(0);
$childTwo = $this->scheduledNodeRepo->find(1);
$this->assertNotNull($childOne);
$this->assertNotNull($childTwo);
$this->assertEquals(
new DateTimeImmutable('2025-01-01'),
$childOne->getDate()
);
$this->assertEquals(
new DateTimeImmutable('2025-01-02'),
$childTwo->getDate()
);
}
public function test_more_scheduled_nodes_than_days(): void
{
$text = $this->textRepo->find(0);
$rootNode = $this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'root node',
parentNode: null,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child 1',
parentNode: $rootNode,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child 2',
parentNode: $rootNode,
));
$this->nodeRepo->create(new CreateNodeDto(
text: $text,
title: 'child 3',
parentNode: $rootNode,
));
$plan = $this->useCase->execute(new CreatePlanRequest(
userId: 0,
name: 'testPlan',
textId: 0,
dateStart: '2025-01-01',
dateEnd: '2025-01-02',
));
$childOne = $this->scheduledNodeRepo->find(0);
$childTwo = $this->scheduledNodeRepo->find(1);
$childThree = $this->scheduledNodeRepo->find(2);
$this->assertNotNull($childOne);
$this->assertNotNull($childTwo);
$this->assertNotNull($childThree);
$this->assertEquals(
new DateTimeImmutable('2025-01-01'),
$childOne->getDate()
);
$this->assertEquals(
new DateTimeImmutable('2025-01-01'),
$childTwo->getDate()
);
$this->assertEquals(
new DateTimeImmutable('2025-01-02'),
$childThree->getDate()
);
}
}