diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..6406599 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,58 @@ +name: CI + +on: + push: + branches: [ develop ] + pull_request: + branches: [ main ] + +jobs: + build-test: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: ${{ secrets.DB_USERNAME }} + POSTGRES_PASSWORD: ${{ secrets.DB_PASSWORD }} + POSTGRES_DB: watchvault + ports: + - 5432:5432 + options: >- + --health-cmd="pg_isready -U postgres -d postgres" + --health-interval=10s + --health-timeout=5s + --health-retries=10 + + env: + SPRING_DATASOURCE_URL: ${{ secrets.DB_URL }} + SPRING_DATASOURCE_USERNAME: ${{ secrets.DB_USERNAME }} + SPRING_DATASOURCE_PASSWORD: ${{ secrets.DB_PASSWORD }} + SPRING_PROFILES_ACTIVE: ${{ secrets.SPRING_PROFILES_ACTIVE }} + JWT_SECRET: ${{ secrets.JWT_SECRET }} + TMDB_TOKEN: ${{ secrets.TMDB_TOKEN }} + TMDB_BASE_URL: ${{ secrets.TMDB_BASE_URL}} + + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "21" + cache: maven + + - name: Build & Test + run: ./mvnw -B -e clean test + + - name: Show surefire reports on failure + if: failure() + run: | + echo "---- SUREFIRE REPORTS ----" + ls -R target/surefire-reports || true + for f in target/surefire-reports/*.txt; do + echo "===== $f =====" + cat "$f" + done diff --git a/src/main/java/com/dizio1/watchvault/common/infrastructure/in/web/exception/GlobalExceptionHandler.java b/src/main/java/com/dizio1/watchvault/common/infrastructure/in/web/exception/GlobalExceptionHandler.java index d1fff6f..f8a4f99 100644 --- a/src/main/java/com/dizio1/watchvault/common/infrastructure/in/web/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/dizio1/watchvault/common/infrastructure/in/web/exception/GlobalExceptionHandler.java @@ -1,6 +1,7 @@ package com.dizio1.watchvault.common.infrastructure.in.web.exception; import com.dizio1.watchvault.movie.domain.exception.MovieNotFoundException; +import com.dizio1.watchvault.review.domain.exception.InvalidShowTypeException; import com.dizio1.watchvault.series.domain.exception.SeriesNotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -29,4 +30,13 @@ public ResponseEntity handleSeriesNotFound(SeriesNotFoundExcep ex.getMessage()); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponseDto); } + + @ExceptionHandler(InvalidShowTypeException.class) + public ResponseEntity handleInvalidShowTypeException(InvalidShowTypeException ex) { + ErrorResponseDto errorResponseDto = new ErrorResponseDto(LocalDateTime.now(), + HttpStatus.BAD_REQUEST.value(), + HttpStatus.BAD_REQUEST.name(), + ex.getMessage()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorResponseDto); + } } diff --git a/src/main/java/com/dizio1/watchvault/movie/application/ports/out/MovieRepositoryPort.java b/src/main/java/com/dizio1/watchvault/movie/application/ports/out/MovieRepositoryPort.java index 776649f..0b170e6 100644 --- a/src/main/java/com/dizio1/watchvault/movie/application/ports/out/MovieRepositoryPort.java +++ b/src/main/java/com/dizio1/watchvault/movie/application/ports/out/MovieRepositoryPort.java @@ -2,13 +2,9 @@ import com.dizio1.watchvault.movie.domain.model.Movie; -import java.util.Optional; - public interface MovieRepositoryPort { Movie registerMovie(Movie movie); - Optional findById(Long id); - boolean existsById(Long id); } diff --git a/src/main/java/com/dizio1/watchvault/movie/infrastructure/out/persistence/JpaMovieRepositoryAdapter.java b/src/main/java/com/dizio1/watchvault/movie/infrastructure/out/persistence/JpaMovieRepositoryAdapter.java index dc3a845..4dd7aac 100644 --- a/src/main/java/com/dizio1/watchvault/movie/infrastructure/out/persistence/JpaMovieRepositoryAdapter.java +++ b/src/main/java/com/dizio1/watchvault/movie/infrastructure/out/persistence/JpaMovieRepositoryAdapter.java @@ -5,8 +5,6 @@ import com.dizio1.watchvault.movie.domain.model.Movie; import org.springframework.stereotype.Component; -import java.util.Optional; - @Component public class JpaMovieRepositoryAdapter implements MovieRepositoryPort { @@ -30,12 +28,6 @@ public Movie registerMovie(Movie movie) { return movieMapper.toModel(saved); } - @Override - public Optional findById(Long id) { - return movieRepository.findById(id) - .map(movieMapper::toModel); - } - @Override public boolean existsById(Long id) { return movieRepository.existsById(id); diff --git a/src/main/java/com/dizio1/watchvault/review/application/ports/in/CreateReviewUseCase.java b/src/main/java/com/dizio1/watchvault/review/application/ports/in/CreateReviewUseCase.java index 98582e2..d7c6687 100644 --- a/src/main/java/com/dizio1/watchvault/review/application/ports/in/CreateReviewUseCase.java +++ b/src/main/java/com/dizio1/watchvault/review/application/ports/in/CreateReviewUseCase.java @@ -1,6 +1,6 @@ package com.dizio1.watchvault.review.application.ports.in; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; public interface CreateReviewUseCase { diff --git a/src/main/java/com/dizio1/watchvault/review/application/ports/in/GetReviewsUseCase.java b/src/main/java/com/dizio1/watchvault/review/application/ports/in/GetReviewsUseCase.java index e75878a..9395d30 100644 --- a/src/main/java/com/dizio1/watchvault/review/application/ports/in/GetReviewsUseCase.java +++ b/src/main/java/com/dizio1/watchvault/review/application/ports/in/GetReviewsUseCase.java @@ -2,7 +2,7 @@ import com.dizio1.watchvault.common.infrastructure.in.web.page.PageResult; import com.dizio1.watchvault.common.infrastructure.in.web.page.PaginationRequest; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; public interface GetReviewsUseCase { diff --git a/src/main/java/com/dizio1/watchvault/review/application/ports/out/ReviewRepositoryPort.java b/src/main/java/com/dizio1/watchvault/review/application/ports/out/ReviewRepositoryPort.java index d69b503..ac6823f 100644 --- a/src/main/java/com/dizio1/watchvault/review/application/ports/out/ReviewRepositoryPort.java +++ b/src/main/java/com/dizio1/watchvault/review/application/ports/out/ReviewRepositoryPort.java @@ -2,7 +2,7 @@ import com.dizio1.watchvault.common.infrastructure.in.web.page.PageResult; import com.dizio1.watchvault.common.infrastructure.in.web.page.PaginationRequest; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; public interface ReviewRepositoryPort { diff --git a/src/main/java/com/dizio1/watchvault/review/application/usecase/CreateReviewUseCaseImpl.java b/src/main/java/com/dizio1/watchvault/review/application/usecase/CreateReviewUseCaseImpl.java index 61adee3..40f2d31 100644 --- a/src/main/java/com/dizio1/watchvault/review/application/usecase/CreateReviewUseCaseImpl.java +++ b/src/main/java/com/dizio1/watchvault/review/application/usecase/CreateReviewUseCaseImpl.java @@ -7,8 +7,8 @@ import com.dizio1.watchvault.review.application.ports.in.CreateReviewUseCase; import com.dizio1.watchvault.review.application.ports.out.ReviewRepositoryPort; import com.dizio1.watchvault.review.application.usecase.result.ShowRegistrationResult; -import com.dizio1.watchvault.review.domain.Review; -import com.dizio1.watchvault.review.domain.ShowType; +import com.dizio1.watchvault.review.domain.model.Review; +import com.dizio1.watchvault.review.domain.model.ShowType; import com.dizio1.watchvault.series.application.ports.out.SeriesCatalogPort; import com.dizio1.watchvault.series.application.ports.out.SeriesRepositoryPort; import com.dizio1.watchvault.series.domain.model.Series; diff --git a/src/main/java/com/dizio1/watchvault/review/application/usecase/GetReviewsUseCaseImpl.java b/src/main/java/com/dizio1/watchvault/review/application/usecase/GetReviewsUseCaseImpl.java index 824989c..c1dfca3 100644 --- a/src/main/java/com/dizio1/watchvault/review/application/usecase/GetReviewsUseCaseImpl.java +++ b/src/main/java/com/dizio1/watchvault/review/application/usecase/GetReviewsUseCaseImpl.java @@ -4,7 +4,7 @@ import com.dizio1.watchvault.common.infrastructure.in.web.page.PaginationRequest; import com.dizio1.watchvault.review.application.ports.in.GetReviewsUseCase; import com.dizio1.watchvault.review.application.ports.out.ReviewRepositoryPort; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; public class GetReviewsUseCaseImpl implements GetReviewsUseCase { diff --git a/src/main/java/com/dizio1/watchvault/review/domain/exception/InvalidShowTypeException.java b/src/main/java/com/dizio1/watchvault/review/domain/exception/InvalidShowTypeException.java new file mode 100644 index 0000000..9761dc0 --- /dev/null +++ b/src/main/java/com/dizio1/watchvault/review/domain/exception/InvalidShowTypeException.java @@ -0,0 +1,7 @@ +package com.dizio1.watchvault.review.domain.exception; + +public class InvalidShowTypeException extends RuntimeException { + public InvalidShowTypeException(String message) { + super("Invalid show type value : " + message); + } +} diff --git a/src/main/java/com/dizio1/watchvault/review/domain/Review.java b/src/main/java/com/dizio1/watchvault/review/domain/model/Review.java similarity index 96% rename from src/main/java/com/dizio1/watchvault/review/domain/Review.java rename to src/main/java/com/dizio1/watchvault/review/domain/model/Review.java index c9fcedd..878d984 100644 --- a/src/main/java/com/dizio1/watchvault/review/domain/Review.java +++ b/src/main/java/com/dizio1/watchvault/review/domain/model/Review.java @@ -1,4 +1,4 @@ -package com.dizio1.watchvault.review.domain; +package com.dizio1.watchvault.review.domain.model; import java.time.LocalDate; diff --git a/src/main/java/com/dizio1/watchvault/review/domain/ShowType.java b/src/main/java/com/dizio1/watchvault/review/domain/model/ShowType.java similarity index 68% rename from src/main/java/com/dizio1/watchvault/review/domain/ShowType.java rename to src/main/java/com/dizio1/watchvault/review/domain/model/ShowType.java index 330d539..9c0b83d 100644 --- a/src/main/java/com/dizio1/watchvault/review/domain/ShowType.java +++ b/src/main/java/com/dizio1/watchvault/review/domain/model/ShowType.java @@ -1,4 +1,6 @@ -package com.dizio1.watchvault.review.domain; +package com.dizio1.watchvault.review.domain.model; + +import com.dizio1.watchvault.review.domain.exception.InvalidShowTypeException; import java.util.Arrays; @@ -21,6 +23,6 @@ public static ShowType from(String value) { return Arrays.stream(ShowType.values()) .filter(t -> t.name().equalsIgnoreCase(value)) .findFirst() - .orElseThrow(IllegalArgumentException::new); + .orElseThrow(() -> new InvalidShowTypeException(value)); } } diff --git a/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/ReviewController.java b/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/ReviewController.java index eb1ded3..2e59c37 100644 --- a/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/ReviewController.java +++ b/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/ReviewController.java @@ -4,7 +4,7 @@ import com.dizio1.watchvault.common.infrastructure.in.web.page.PageResult; import com.dizio1.watchvault.review.application.ports.in.CreateReviewUseCase; import com.dizio1.watchvault.review.application.ports.in.GetReviewsUseCase; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; import com.dizio1.watchvault.review.infrastructure.in.web.dto.CreateReviewRequest; import com.dizio1.watchvault.review.infrastructure.in.web.dto.RestReviewMapper; import com.dizio1.watchvault.review.infrastructure.in.web.dto.ReviewResponse; diff --git a/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/dto/RestReviewMapper.java b/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/dto/RestReviewMapper.java index 81ed21e..843c75e 100644 --- a/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/dto/RestReviewMapper.java +++ b/src/main/java/com/dizio1/watchvault/review/infrastructure/in/web/dto/RestReviewMapper.java @@ -1,7 +1,7 @@ package com.dizio1.watchvault.review.infrastructure.in.web.dto; -import com.dizio1.watchvault.review.domain.Review; -import com.dizio1.watchvault.review.domain.ShowType; +import com.dizio1.watchvault.review.domain.model.Review; +import com.dizio1.watchvault.review.domain.model.ShowType; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewMapper.java b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewMapper.java index cdcd53e..1a48f34 100644 --- a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewMapper.java +++ b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewMapper.java @@ -1,6 +1,6 @@ package com.dizio1.watchvault.review.infrastructure.out.persistence; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewRepositoryAdapter.java b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewRepositoryAdapter.java index 2e400d3..ba8c5a8 100644 --- a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewRepositoryAdapter.java +++ b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/JpaReviewRepositoryAdapter.java @@ -4,7 +4,7 @@ import com.dizio1.watchvault.common.infrastructure.in.web.page.PageResult; import com.dizio1.watchvault.common.infrastructure.in.web.page.PaginationRequest; import com.dizio1.watchvault.review.application.ports.out.ReviewRepositoryPort; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/ReviewEntity.java b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/ReviewEntity.java index f49eba7..8d629f9 100644 --- a/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/ReviewEntity.java +++ b/src/main/java/com/dizio1/watchvault/review/infrastructure/out/persistence/ReviewEntity.java @@ -1,6 +1,6 @@ package com.dizio1.watchvault.review.infrastructure.out.persistence; -import com.dizio1.watchvault.review.domain.ShowType; +import com.dizio1.watchvault.review.domain.model.ShowType; import jakarta.persistence.*; import java.time.LocalDate; diff --git a/src/main/java/com/dizio1/watchvault/user/domain/model/User.java b/src/main/java/com/dizio1/watchvault/user/domain/model/User.java index faebfdc..05e1b5b 100644 --- a/src/main/java/com/dizio1/watchvault/user/domain/model/User.java +++ b/src/main/java/com/dizio1/watchvault/user/domain/model/User.java @@ -1,6 +1,6 @@ package com.dizio1.watchvault.user.domain.model; -import com.dizio1.watchvault.review.domain.Review; +import com.dizio1.watchvault.review.domain.model.Review; import java.util.List; diff --git a/src/test/java/com/dizio1/watchvault/movie/application/usecase/SearchMovieUseCaseImplTest.java b/src/test/java/com/dizio1/watchvault/movie/application/usecase/SearchMovieUseCaseImplTest.java new file mode 100644 index 0000000..26d5095 --- /dev/null +++ b/src/test/java/com/dizio1/watchvault/movie/application/usecase/SearchMovieUseCaseImplTest.java @@ -0,0 +1,65 @@ +package com.dizio1.watchvault.movie.application.usecase; + +import com.dizio1.watchvault.genre.domain.model.Genre; +import com.dizio1.watchvault.movie.application.ports.out.MovieCatalogPort; +import com.dizio1.watchvault.movie.domain.model.CrewMember; +import com.dizio1.watchvault.movie.domain.model.Movie; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class SearchMovieUseCaseImplTest { + @Mock + private MovieCatalogPort movieCatalog; + @InjectMocks + private SearchMovieUseCaseImpl searchMovieUseCaseImpl; + + @Test + public void searchMovie_givenExistingMovie_returnsMovieWithDirector() { + Movie movie = new Movie(); + movie.setId(1L); + movie.setDirectedBy("Quentin Tarantino"); + movie.setGenres(List.of(new Genre(1L, "Drama"), new Genre(2L, "Comedy"))); + movie.setRuntime(121); + movie.setReleaseDate(LocalDate.of(2009, 11, 20)); + movie.setOverview("Uma Thurman feet"); + movie.setTitle("Pulp Fiction"); + + CrewMember tarantino = new CrewMember(1L, + "Quentin Tarantino", + 1, + "Director", + "Directing"); + CrewMember crewMember = new CrewMember(2L, + "John Doe", + 1, + "Make up", + "Make Up Artist"); + + when(movieCatalog.searchByTitle(movie.getTitle())).thenReturn(movie); + when(movieCatalog.searchCrewMembers(movie.getTitle())).thenReturn(List.of(tarantino, crewMember)); + + Movie result = searchMovieUseCaseImpl.searchMovie(movie.getTitle()); + + assertEquals(movie.getTitle(), result.getTitle()); + assertEquals(movie.getDirectedBy(), result.getDirectedBy()); + assertEquals(movie.getGenres(), result.getGenres()); + assertEquals(movie.getId(), result.getId()); + assertEquals(movie.getReleaseDate(), result.getReleaseDate()); + assertEquals(movie.getOverview(), result.getOverview()); + assertEquals(movie.getRuntime(), result.getRuntime()); + + verify(movieCatalog).searchCrewMembers(movie.getTitle()); + verify(movieCatalog).searchByTitle(movie.getTitle()); + } +}