From 3336847e819cf8b88cf1b5a640aca455b51e3d75 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 5 Apr 2021 23:21:00 +0200 Subject: [PATCH] Add search Video by term in title use case. --- .../video/application/search/VideosSearcher.scala | 2 ++ .../codely/mooc/video/domain/VideoRepository.scala | 2 ++ .../repository/DoobieMySqlVideoRepository.scala | 6 ++++++ .../application/search/VideosSearcherShould.scala | 10 ++++++++++ .../DoobieMySqlVideoRepositoryShould.scala | 13 +++++++++++++ .../repository/VideoRepositoryMock.scala | 5 +++++ 6 files changed, 38 insertions(+) diff --git a/src/mooc/main/tv/codely/mooc/video/application/search/VideosSearcher.scala b/src/mooc/main/tv/codely/mooc/video/application/search/VideosSearcher.scala index 3b65881..9170f32 100644 --- a/src/mooc/main/tv/codely/mooc/video/application/search/VideosSearcher.scala +++ b/src/mooc/main/tv/codely/mooc/video/application/search/VideosSearcher.scala @@ -6,4 +6,6 @@ import scala.concurrent.Future final class VideosSearcher(repository: VideoRepository) { def all(): Future[Seq[Video]] = repository.all() + + def findByTermInTitle(term: String): Future[Seq[Video]] = repository.findByTermInTitle(term) } diff --git a/src/mooc/main/tv/codely/mooc/video/domain/VideoRepository.scala b/src/mooc/main/tv/codely/mooc/video/domain/VideoRepository.scala index d770462..468279f 100644 --- a/src/mooc/main/tv/codely/mooc/video/domain/VideoRepository.scala +++ b/src/mooc/main/tv/codely/mooc/video/domain/VideoRepository.scala @@ -5,5 +5,7 @@ import scala.concurrent.Future trait VideoRepository { def all(): Future[Seq[Video]] + def findByTermInTitle(term: String): Future[Seq[Video]] + def save(video: Video): Future[Unit] } diff --git a/src/mooc/main/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepository.scala b/src/mooc/main/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepository.scala index 0f2dfdd..2679d43 100644 --- a/src/mooc/main/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepository.scala +++ b/src/mooc/main/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepository.scala @@ -12,6 +12,12 @@ final class DoobieMySqlVideoRepository(db: DoobieDbConnection)(implicit executio override def all(): Future[Seq[Video]] = db.read(sql"SELECT video_id, title, duration_in_seconds, category, creator_id FROM videos".query[Video].to[Seq]) + override def findByTermInTitle(term: String) = + db.read( + sql"SELECT video_id, title, duration_in_seconds, category, creator_id FROM videos WHERE title LIKE CONCAT('%', $term, '%')" + .query[Video] + .to[Seq]) + override def save(video: Video): Future[Unit] = sql"INSERT INTO videos(video_id, title, duration_in_seconds, category, creator_id) VALUES (${video.id}, ${video.title}, ${video.duration}, ${video.category}, ${video.creatorId})".update.run .transact(db.transactor) diff --git a/src/mooc/test/tv/codely/mooc/video/application/search/VideosSearcherShould.scala b/src/mooc/test/tv/codely/mooc/video/application/search/VideosSearcherShould.scala index 32897ce..ff93881 100644 --- a/src/mooc/test/tv/codely/mooc/video/application/search/VideosSearcherShould.scala +++ b/src/mooc/test/tv/codely/mooc/video/application/search/VideosSearcherShould.scala @@ -16,4 +16,14 @@ final class VideosSearcherShould extends UnitTestCase with VideoRepositoryMock { searcher.all().futureValue shouldBe existingVideos } + + "search all videos that contain a term in title" in { + val matchingVideo = VideoMother.random + val anotherMatchingVideo = VideoMother.random + val matchingVideos = Seq(matchingVideo, anotherMatchingVideo) + val term = "Term" + repositoryShouldFindByTermInTitle(term, matchingVideos) + + searcher.findByTermInTitle(term).futureValue shouldBe matchingVideos + } } diff --git a/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepositoryShould.scala b/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepositoryShould.scala index f11e509..2a9ab17 100644 --- a/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepositoryShould.scala +++ b/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/DoobieMySqlVideoRepositoryShould.scala @@ -2,6 +2,7 @@ package tv.codely.mooc.video.infrastructure.repository import tv.codely.mooc.video.VideoIntegrationTestCase import tv.codely.mooc.video.domain.VideoMother +import tv.codely.mooc.video.domain.VideoTitleMother import doobie.implicits._ import org.scalatest.BeforeAndAfterEach @@ -29,4 +30,16 @@ final class DoobieMySqlVideoRepositoryShould extends VideoIntegrationTestCase wi repository.all().futureValue shouldBe videos } + + "search all videos that contain a term in title" in { + val term = "Term" + val videoMatch = VideoMother.random.copy(title = VideoTitleMother("This has a Term inside")) + val videoNoMatch = VideoMother.random.copy(title = VideoTitleMother("This has not a ? inside")) + + repository.save(videoMatch).futureValue + repository.save(videoNoMatch).futureValue + + repository.findByTermInTitle(term).futureValue should contain(videoMatch) + repository.findByTermInTitle(term).futureValue should not contain (videoNoMatch) + } } diff --git a/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/VideoRepositoryMock.scala b/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/VideoRepositoryMock.scala index 6433762..e0d926f 100644 --- a/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/VideoRepositoryMock.scala +++ b/src/mooc/test/tv/codely/mooc/video/infrastructure/repository/VideoRepositoryMock.scala @@ -20,4 +20,9 @@ protected[video] trait VideoRepositoryMock extends MockFactory { (repository.all _) .expects() .returning(Future.successful(videos)) + + protected def repositoryShouldFindByTermInTitle(term: String, videos: Seq[Video]): Unit = + (repository.findByTermInTitle _) + .expects(term) + .returning(Future.successful(videos)) }