diff --git a/docker-compose.yml b/docker-compose.yml index 2af2539f..91ba4381 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,22 +27,25 @@ services: mooc_mysql: container_name: codelytv-php_ddd_skeleton-mooc-mysql - image: mysql:8.0 + image: mysql/mysql-server:8.0.23 ports: - 3360:3306 environment: - MYSQL_ROOT_PASSWORD= - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_ROOT_HOST=% healthcheck: test: ["CMD", "mysqladmin", "--user=root", "--password=", "--host=127.0.0.1", "ping", "--silent"] interval: 2s timeout: 10s retries: 10 - command: ["--default-authentication-plugin=mysql_native_password"] + command: ["--lower_case_table_names=1"] + + backoffice_elasticsearch: container_name: codelytv-php_ddd_skeleton-backoffice-elastic - image: docker.elastic.co/elasticsearch/elasticsearch:6.8.10 + image: docker.elastic.co/elasticsearch/elasticsearch:7.12.0 ports: - 9200:9200 - 9300:9300 @@ -101,4 +104,4 @@ services: - shared_rabbitmq - shared_prometheus - mooc_mysql - command: symfony serve --dir=apps/mooc/backend/public --port=8030 --force-php-discovery + command: symfony serve --dir=apps/mooc/backend/public --port=8030 --force-php-discovery \ No newline at end of file diff --git a/src/Mooc/Courses/Application/Find/AllCoursesFinder.php b/src/Mooc/Courses/Application/Find/AllCoursesFinder.php new file mode 100644 index 00000000..7cb828d5 --- /dev/null +++ b/src/Mooc/Courses/Application/Find/AllCoursesFinder.php @@ -0,0 +1,26 @@ +repository->findAll(); + + if (null === $courses) { + throw new CoursesNotFound(); + } + + return $courses; + } +} diff --git a/src/Mooc/Courses/Application/Find/CoursesResponse.php b/src/Mooc/Courses/Application/Find/CoursesResponse.php new file mode 100644 index 00000000..35fbfe0c --- /dev/null +++ b/src/Mooc/Courses/Application/Find/CoursesResponse.php @@ -0,0 +1,25 @@ +course; + } + + +} diff --git a/src/Mooc/Courses/Application/Find/FindAllCoursesQuery.php b/src/Mooc/Courses/Application/Find/FindAllCoursesQuery.php new file mode 100644 index 00000000..70ea9969 --- /dev/null +++ b/src/Mooc/Courses/Application/Find/FindAllCoursesQuery.php @@ -0,0 +1,12 @@ +finder->__invoke()); + } +} diff --git a/src/Mooc/Courses/Domain/CourseRepository.php b/src/Mooc/Courses/Domain/CourseRepository.php index bf12fad1..b3a3e534 100644 --- a/src/Mooc/Courses/Domain/CourseRepository.php +++ b/src/Mooc/Courses/Domain/CourseRepository.php @@ -11,4 +11,6 @@ interface CourseRepository public function save(Course $course): void; public function search(CourseId $id): ?Course; + + public function findAll(): ?array; } diff --git a/src/Mooc/Courses/Domain/CoursesNotFound.php b/src/Mooc/Courses/Domain/CoursesNotFound.php new file mode 100644 index 00000000..e64002da --- /dev/null +++ b/src/Mooc/Courses/Domain/CoursesNotFound.php @@ -0,0 +1,25 @@ +repository(Course::class)->find($id); } + + public function findAll(): ?array + { + return $this->repository(Course::class)->findAll(); + } } diff --git a/src/Mooc/Courses/Infrastructure/Persistence/FileCourseRepository.php b/src/Mooc/Courses/Infrastructure/Persistence/FileCourseRepository.php index 05124081..6948731a 100644 --- a/src/Mooc/Courses/Infrastructure/Persistence/FileCourseRepository.php +++ b/src/Mooc/Courses/Infrastructure/Persistence/FileCourseRepository.php @@ -28,4 +28,9 @@ private function fileName(string $id): string { return sprintf('%s.%s.repo', self::FILE_PATH, $id); } + + public function findAll(): ?array + { + return $this->findAll(); + } } diff --git a/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommand.php b/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommand.php new file mode 100644 index 00000000..dfdc9634 --- /dev/null +++ b/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommand.php @@ -0,0 +1,28 @@ +id; + } + + public function getTitle(): string + { + return $this->title; + } + +} diff --git a/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommandHandler.php b/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommandHandler.php new file mode 100644 index 00000000..f4c208cd --- /dev/null +++ b/src/Mooc/Videos/Application/Update/UpdateVideoTitleCommandHandler.php @@ -0,0 +1,25 @@ +getId()); + $title = new VideoTitle($command->getTitle()); + + $this->titleUpdater->__invoke($id, $title); + } +} diff --git a/tests/Mooc/Courses/Application/Create/CreateCourseCommandHandlerTest.php b/tests/Mooc/Courses/Application/Create/CreateCourseCommandHandlerTest.php index 6a85c1f1..dcf5b35c 100644 --- a/tests/Mooc/Courses/Application/Create/CreateCourseCommandHandlerTest.php +++ b/tests/Mooc/Courses/Application/Create/CreateCourseCommandHandlerTest.php @@ -34,4 +34,4 @@ public function it_should_create_a_valid_course(): void $this->dispatch($command, $this->handler); } -} +} \ No newline at end of file diff --git a/tests/Mooc/Courses/Application/Find/CourseFinderTest.php b/tests/Mooc/Courses/Application/Find/CourseFinderTest.php new file mode 100644 index 00000000..e6a500e5 --- /dev/null +++ b/tests/Mooc/Courses/Application/Find/CourseFinderTest.php @@ -0,0 +1,47 @@ +finder = new CourseFinder($this->repository()); + } + + /** @test */ + public function it_should_throw_an_exception_when_the_course_not_exist(): void + { + $this->expectException(CourseNotExist::class); + + $id = CourseIdMother::create(); + + $this->shouldSearch($id, null); + + $this->finder->__invoke($id); + } + + /** @test */ + public function it_should_find_an_existing_courses(): void + { + $course = CourseMother::create(); + + $this->shouldSearch($course->id(), $course); + + $courseFromRepository = $this->finder->__invoke($course->id()); + + $this->assertEquals($courseFromRepository, $course); + } +} \ No newline at end of file diff --git a/tests/Mooc/Courses/Application/Find/FindAllCoursesQueryHandlerTest.php b/tests/Mooc/Courses/Application/Find/FindAllCoursesQueryHandlerTest.php new file mode 100644 index 00000000..e2db6893 --- /dev/null +++ b/tests/Mooc/Courses/Application/Find/FindAllCoursesQueryHandlerTest.php @@ -0,0 +1,41 @@ +handler = new FindAllCoursesQueryHandler(new AllCoursesFinder($this->repository())); + } + + + /** @test */ + public function it_should_find_all_existing_courses(): void + { + $courses = [ + CourseMother::create(), + CourseMother::create() + ]; + + $this->shouldFindAll($courses); + $coursesResponse = CoursesResponseMother::create($courses); + $courseFromRepository = $this->handler->__invoke(new FindAllCoursesQuery()); + + $this->assertEquals($courseFromRepository, $coursesResponse); + } +} diff --git a/tests/Mooc/Courses/Application/Update/CourseRenamerTest.php b/tests/Mooc/Courses/Application/Update/CourseRenamerTest.php index 2815aa7f..240cfc62 100644 --- a/tests/Mooc/Courses/Application/Update/CourseRenamerTest.php +++ b/tests/Mooc/Courses/Application/Update/CourseRenamerTest.php @@ -48,4 +48,4 @@ public function it_should_throw_an_exception_when_the_course_not_exist(): void $this->renamer->__invoke($id, CourseNameMother::create()); } -} +} \ No newline at end of file diff --git a/tests/Mooc/Courses/CoursesModuleUnitTestCase.php b/tests/Mooc/Courses/CoursesModuleUnitTestCase.php index 99aec424..c453dfdd 100644 --- a/tests/Mooc/Courses/CoursesModuleUnitTestCase.php +++ b/tests/Mooc/Courses/CoursesModuleUnitTestCase.php @@ -32,6 +32,14 @@ protected function shouldSearch(CourseId $id, ?Course $course): void ->andReturn($course); } + protected function shouldFindAll(?array $courses): void + { + $this->repository() + ->shouldReceive('findAll') + ->once() + ->andReturn($courses); + } + protected function repository(): CourseRepository|MockInterface { return $this->repository = $this->repository ?? $this->mock(CourseRepository::class); diff --git a/tests/Mooc/Courses/Domain/CoursesResponseMother.php b/tests/Mooc/Courses/Domain/CoursesResponseMother.php new file mode 100644 index 00000000..a2de9d14 --- /dev/null +++ b/tests/Mooc/Courses/Domain/CoursesResponseMother.php @@ -0,0 +1,16 @@ +handler = new UpdateVideoTitleCommandHandler(new VideoTitleUpdater($this->repository())); + } + + /** @test */ + public function it_should_update_video_title_when_video_exists(): void + { + $video = VideoMother::create(); + $newTitle = VideoTitleMother::create(); + $command = UpdateVideoTitleCommandMother::withIdAndTitle($video->id(), $newTitle); + $renamedVideo = DuplicatorMother::with($video, ['title' => $newTitle]); + + $this->shouldSearch($video->id(), $video); + $this->shouldSave($renamedVideo); + + $this->handler->__invoke($command); + } + + + /** @test */ + public function it_should_throw_an_exception_when_the_video_does_not_exist(): void + { + $this->expectException(VideoNotFound::class); + + $id = VideoIdMother::create(); + $command = UpdateVideoTitleCommandMother::withId($id); + + $this->shouldSearch($id, null); + + $this->handler->__invoke($command); + } + +} diff --git a/tests/Mooc/Videos/Application/Update/UpdateVideoTitleCommandMother.php b/tests/Mooc/Videos/Application/Update/UpdateVideoTitleCommandMother.php new file mode 100644 index 00000000..e7248da6 --- /dev/null +++ b/tests/Mooc/Videos/Application/Update/UpdateVideoTitleCommandMother.php @@ -0,0 +1,34 @@ +value() ?? VideoIdMother::create()->value(), + $title->value() ?? VideoTitleMother::create()->value() + ); + } + + public static function withId(VideoId $id): UpdateVideoTitleCommand + { + return self::create($id, VideoTitleMother::create()); + } + + public static function withIdAndTitle(VideoId $id, VideoTitle $title): UpdateVideoTitleCommand + { + return self::create($id, $title); + } +} diff --git a/tests/Mooc/Videos/Domain/VideoIdMother.php b/tests/Mooc/Videos/Domain/VideoIdMother.php new file mode 100644 index 00000000..3558b16c --- /dev/null +++ b/tests/Mooc/Videos/Domain/VideoIdMother.php @@ -0,0 +1,17 @@ +id()), + VideoTypeMother::create($request->type()), + VideoTitleMother::create($request->title()), + VideoUrlMother::create($request->url()), + CourseIdMother::create($request->courseId()) + ); + } +} diff --git a/tests/Mooc/Videos/Domain/VideoTitleMother.php b/tests/Mooc/Videos/Domain/VideoTitleMother.php new file mode 100644 index 00000000..4cfb4f1c --- /dev/null +++ b/tests/Mooc/Videos/Domain/VideoTitleMother.php @@ -0,0 +1,16 @@ +repository() + ->shouldReceive('save') + ->with($this->similarTo($video)) + ->once() + ->andReturnNull(); + } + + + protected function shouldSearch(VideoId $id, ?Video $video): void + { + $this->repository() + ->shouldReceive('search') + ->with($this->similarTo($id)) + ->once() + ->andReturn($video); + } + + protected function repository(): VideoRepository|MockInterface + { + return $this->repository = $this->repository ?? $this->mock(VideoRepository::class); + } +} diff --git a/tests/Shared/Domain/TypeMother.php b/tests/Shared/Domain/TypeMother.php new file mode 100644 index 00000000..ca6b887b --- /dev/null +++ b/tests/Shared/Domain/TypeMother.php @@ -0,0 +1,17 @@ +value(); + } +} diff --git a/tests/Shared/Domain/UrlMother.php b/tests/Shared/Domain/UrlMother.php new file mode 100644 index 00000000..5bb1f3f2 --- /dev/null +++ b/tests/Shared/Domain/UrlMother.php @@ -0,0 +1,13 @@ +url; + } +}