From 6c5200d4bde68be1c261f15cd881fe75a3fb2bda Mon Sep 17 00:00:00 2001 From: David Rabko Date: Sat, 30 Mar 2024 09:54:58 +0100 Subject: [PATCH 1/4] Add endpoint for updating a playlist title --- .../security/SecurityConfiguration.java | 2 + .../ypm/controller/PlayListController.java | 35 ++++++++----- .../java/com/ypm/service/PlayListService.java | 51 +++++++++++++++++++ ...YouTubeService.java => VideosService.java} | 15 ++---- src/main/resources/application.yml | 2 +- .../controller/PlayListControllerTest.java | 22 ++++---- .../com/ypm/service/YouTubeServiceTest.java | 9 ++-- 7 files changed, 99 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/ypm/service/PlayListService.java rename src/main/java/com/ypm/service/{YouTubeService.java => VideosService.java} (64%) diff --git a/src/main/java/com/ypm/config/security/SecurityConfiguration.java b/src/main/java/com/ypm/config/security/SecurityConfiguration.java index 5bff3d5..69096e5 100644 --- a/src/main/java/com/ypm/config/security/SecurityConfiguration.java +++ b/src/main/java/com/ypm/config/security/SecurityConfiguration.java @@ -4,6 +4,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; @@ -14,6 +15,7 @@ public class SecurityConfiguration { @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http + .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2Login(config -> { config.defaultSuccessUrl("/auth/success", true); diff --git a/src/main/java/com/ypm/controller/PlayListController.java b/src/main/java/com/ypm/controller/PlayListController.java index c6cabc2..10e8fce 100644 --- a/src/main/java/com/ypm/controller/PlayListController.java +++ b/src/main/java/com/ypm/controller/PlayListController.java @@ -1,40 +1,51 @@ package com.ypm.controller; import com.google.api.services.youtube.model.Playlist; +import com.google.api.services.youtube.model.PlaylistSnippet; import com.google.api.services.youtube.model.VideoSnippet; -import com.ypm.service.YouTubeService; +import com.ypm.service.PlayListService; +import com.ypm.service.VideosService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.List; @RestController -@RequestMapping("/playlist") +@RequestMapping("/playlists") @RequiredArgsConstructor public class PlayListController { - private final YouTubeService youTubeService; + private final PlayListService playListService; + private final VideosService videosService; - @GetMapping("/list") + @GetMapping public ResponseEntity> getPlayLists( @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication) throws IOException { String accessToken = authentication.getAccessToken().getTokenValue(); - return ResponseEntity.ok(youTubeService.getMyPlayLists(accessToken)); + return ResponseEntity.ok(playListService.getMyPlayLists(accessToken)); } - @GetMapping("/{playlistId}/videos") - public ResponseEntity> getVideos( + @GetMapping("/{playlistId}") + public ResponseEntity> getPlayListVideos( @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, @PathVariable String playlistId) throws IOException { String accessToken = authentication.getAccessToken().getTokenValue(); - return ResponseEntity.ok(youTubeService.getPlayListVideos(accessToken, playlistId)); + return ResponseEntity.ok(videosService.getPlayListVideos(accessToken, playlistId)); + } + + @PutMapping("/{playlistId}/updateTitle") + public ResponseEntity updatePlayListName( + @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, + @PathVariable String playlistId, + @RequestBody PlaylistSnippet dataWithUpdatedTitle) throws IOException { + + String accessToken = authentication.getAccessToken().getTokenValue(); + String newTitle = dataWithUpdatedTitle.getTitle(); + return ResponseEntity.ok(playListService.updatePlayListName(accessToken, playlistId, newTitle)); } } diff --git a/src/main/java/com/ypm/service/PlayListService.java b/src/main/java/com/ypm/service/PlayListService.java new file mode 100644 index 0000000..bc8e9e6 --- /dev/null +++ b/src/main/java/com/ypm/service/PlayListService.java @@ -0,0 +1,51 @@ +package com.ypm.service; + +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.model.Playlist; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PlayListService { + + private final YouTube youTubeClient; + + public List getMyPlayLists(String accessToken) throws IOException { + var request = youTubeClient.playlists().list(List.of("snippet")); + var response = request + .setAccessToken(accessToken) + .setMine(true) + .execute(); + + return response.getItems(); + } + + public Playlist updatePlayListName(String accessToken, String playListId, String newTitle) + throws IOException { + + Playlist playlistToEdit = getPlayListById(accessToken, playListId); + playlistToEdit.getSnippet().setTitle(newTitle); + var request = youTubeClient.playlists().update(List.of("snippet"), playlistToEdit); + return request.setAccessToken(accessToken).execute(); + } + + + public Playlist getPlayListById(String accessToken, String playListId) throws IOException { + var request = youTubeClient.playlists().list(List.of("snippet")); + var response = request + .setAccessToken(accessToken) + .setMine(true) + .execute(); + + return response + .getItems() + .stream() + .filter(playlist -> playlist.getId().equals(playListId)) + .findFirst() + .orElseThrow(() -> new RuntimeException("Playlist not found.")); + } +} diff --git a/src/main/java/com/ypm/service/YouTubeService.java b/src/main/java/com/ypm/service/VideosService.java similarity index 64% rename from src/main/java/com/ypm/service/YouTubeService.java rename to src/main/java/com/ypm/service/VideosService.java index 8d68ed3..40f7054 100644 --- a/src/main/java/com/ypm/service/YouTubeService.java +++ b/src/main/java/com/ypm/service/VideosService.java @@ -1,7 +1,6 @@ package com.ypm.service; import com.google.api.services.youtube.YouTube; -import com.google.api.services.youtube.model.Playlist; import com.google.api.services.youtube.model.VideoSnippet; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,21 +10,13 @@ @Service @RequiredArgsConstructor -public class YouTubeService { +public class VideosService { private final YouTube youTubeClient; - public List getMyPlayLists(String accessToken) throws IOException { - var request = youTubeClient.playlists().list(List.of("snippet")); - var response = request - .setAccessToken(accessToken) - .setMine(true) - .execute(); - - return response.getItems(); - } + public List getPlayListVideos(String accessToken, String playListId) + throws IOException { - public List getPlayListVideos(String accessToken, String playListId) throws IOException { var request = youTubeClient.playlistItems().list(List.of("snippet")); var response = request .setAccessToken(accessToken) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8189c68..dcb3cbc 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,7 +15,7 @@ spring: client-name: Google client-id: ${google.application.client-id} client-secret: ${google.application.client-secret} - scope: profile, email, https://www.googleapis.com/auth/youtube.readonly + scope: profile, email, https://www.googleapis.com/auth/youtube authorization-grant-type: authorization_code redirect-uri: http://localhost:8080/login/oauth2/code/google provider: diff --git a/src/test/java/com/ypm/controller/PlayListControllerTest.java b/src/test/java/com/ypm/controller/PlayListControllerTest.java index 3831e01..5ca838e 100644 --- a/src/test/java/com/ypm/controller/PlayListControllerTest.java +++ b/src/test/java/com/ypm/controller/PlayListControllerTest.java @@ -3,7 +3,8 @@ import com.google.api.services.youtube.model.Playlist; import com.google.api.services.youtube.model.PlaylistSnippet; import com.google.api.services.youtube.model.VideoSnippet; -import com.ypm.service.YouTubeService; +import com.ypm.service.PlayListService; +import com.ypm.service.VideosService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -33,38 +34,41 @@ class PlayListControllerTest { private MockMvc mockMvc; @MockBean - private YouTubeService youTubeService; + private PlayListService playListService; + + @MockBean + private VideosService videosService; @Test void givenCorrectRequest_whenGetPlayLists_thenResponseContainsPlayListName() throws Exception { Playlist playlist = new Playlist(); playlist.setSnippet(new PlaylistSnippet().setTitle("Test Playlist")); List playlists = Collections.singletonList(playlist); - when(youTubeService.getMyPlayLists(any())).thenReturn(playlists); + when(playListService.getMyPlayLists(any())).thenReturn(playlists); - mockMvc.perform(get("/playlist/list") + mockMvc.perform(get("/playlists") .with(oauth2Login() .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")))) .andExpect(status().isOk()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$[0].snippet.title").value("Test Playlist")); - verify(youTubeService, times(1)).getMyPlayLists(any()); + verify(playListService, times(1)).getMyPlayLists(any()); } @Test - void givenCorrectRequest_whenGetVideos_thenResponseContainsVideoTitle() throws Exception { + void givenCorrectRequest_whenGetPlayListVideos_thenResponseContainsVideoTitle() throws Exception { VideoSnippet video = new VideoSnippet().setTitle("Test Video"); List videos = Collections.singletonList(video); - when(youTubeService.getPlayListVideos(any(), any())).thenReturn(videos); + when(videosService.getPlayListVideos(any(), any())).thenReturn(videos); - mockMvc.perform(get("/playlist/{playlistId}/videos", "playlist_id") + mockMvc.perform(get("/playlists/{playlistId}", "playlistId") .with(oauth2Login() .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")))) .andExpect(status().isOk()) .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$[0].title").value("Test Video")); - verify(youTubeService, times(1)).getPlayListVideos(any(), any()); + verify(videosService, times(1)).getPlayListVideos(any(), any()); } } diff --git a/src/test/java/com/ypm/service/YouTubeServiceTest.java b/src/test/java/com/ypm/service/YouTubeServiceTest.java index 4f874bb..a3ecbe2 100644 --- a/src/test/java/com/ypm/service/YouTubeServiceTest.java +++ b/src/test/java/com/ypm/service/YouTubeServiceTest.java @@ -23,7 +23,10 @@ class YouTubeServiceTest { private YouTube youTubeClient; @InjectMocks - private YouTubeService youTubeService; + private PlayListService playListService; + + @InjectMocks + private VideosService videosService; @Test void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { @@ -40,7 +43,7 @@ void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { when(playlistsList.setMine(true)).thenReturn(playlistsList); when(playlistsList.execute()).thenReturn(playlistsListResponse); - List result = youTubeService.getMyPlayLists(accessToken); + List result = playListService.getMyPlayLists(accessToken); assertEquals(1, result.size()); assertEquals(expectedPlaylist, result.get(0)); @@ -65,7 +68,7 @@ void testGetPlayListVideos() throws IOException { when(playlistItemsList.setPlaylistId(playlistId)).thenReturn(playlistItemsList); when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); - List result = youTubeService.getPlayListVideos(accessToken, playlistId); + List result = videosService.getPlayListVideos(accessToken, playlistId); assertEquals(1, result.size()); assertEquals("Video Title", result.get(0).getTitle()); From bc858dcefd42bdb2344f0106ea1dc3ca90fc1860 Mon Sep 17 00:00:00 2001 From: David Rabko Date: Mon, 1 Apr 2024 15:16:17 +0200 Subject: [PATCH 2/4] Add endpoint to move videos between playlists --- .../youtube/YouTubeClientConfiguration.java | 2 - .../com/ypm/controller/AuthController.java | 19 ++--- .../ypm/controller/PlayListController.java | 40 +++++++-- .../com/ypm/controller/VideoController.java | 31 +++++++ .../java/com/ypm/service/PlayListService.java | 34 ++++---- .../java/com/ypm/service/VideoService.java | 83 +++++++++++++++++++ .../java/com/ypm/service/VideosService.java | 32 ------- .../controller/PlayListControllerTest.java | 15 ++-- .../ypm/controller/VideoControllerTest.java | 40 +++++++++ .../com/ypm/service/YouTubeServiceTest.java | 8 +- 10 files changed, 225 insertions(+), 79 deletions(-) create mode 100644 src/main/java/com/ypm/controller/VideoController.java create mode 100644 src/main/java/com/ypm/service/VideoService.java delete mode 100644 src/main/java/com/ypm/service/VideosService.java create mode 100644 src/test/java/com/ypm/controller/VideoControllerTest.java diff --git a/src/main/java/com/ypm/config/youtube/YouTubeClientConfiguration.java b/src/main/java/com/ypm/config/youtube/YouTubeClientConfiguration.java index a5ea84f..5a5edeb 100644 --- a/src/main/java/com/ypm/config/youtube/YouTubeClientConfiguration.java +++ b/src/main/java/com/ypm/config/youtube/YouTubeClientConfiguration.java @@ -6,13 +6,11 @@ import com.google.api.services.youtube.YouTube; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; import java.io.IOException; import java.security.GeneralSecurityException; @Configuration -@Lazy public class YouTubeClientConfiguration { @Bean diff --git a/src/main/java/com/ypm/controller/AuthController.java b/src/main/java/com/ypm/controller/AuthController.java index 6579486..256ec87 100644 --- a/src/main/java/com/ypm/controller/AuthController.java +++ b/src/main/java/com/ypm/controller/AuthController.java @@ -12,22 +12,21 @@ public class AuthController { @GetMapping("/success") public ModelAndView success() { - ModelAndView modelAndView = new ModelAndView("auth"); - modelAndView.addObject("type", "success"); - modelAndView.addObject("title", "Login Successful"); - modelAndView.addObject("message", + return getModelAndView("success", "Login Success", "Welcome back! You have successfully logged in."); - - return modelAndView; } @GetMapping("/error") public ModelAndView error() { + return getModelAndView("error", "Login Error", + "An error occurred while logging in. Please try again."); + } + + private ModelAndView getModelAndView(String type, String title, String message) { ModelAndView modelAndView = new ModelAndView("auth"); - modelAndView.addObject("type", "error"); - modelAndView.addObject("title", "Login Error"); - modelAndView.addObject("message", - "Sorry, there was an error with your login credentials. Please try again."); + modelAndView.addObject("type", type); + modelAndView.addObject("title", title); + modelAndView.addObject("message", message); return modelAndView; } diff --git a/src/main/java/com/ypm/controller/PlayListController.java b/src/main/java/com/ypm/controller/PlayListController.java index 10e8fce..a4c2d3a 100644 --- a/src/main/java/com/ypm/controller/PlayListController.java +++ b/src/main/java/com/ypm/controller/PlayListController.java @@ -1,10 +1,10 @@ package com.ypm.controller; import com.google.api.services.youtube.model.Playlist; +import com.google.api.services.youtube.model.PlaylistItem; import com.google.api.services.youtube.model.PlaylistSnippet; -import com.google.api.services.youtube.model.VideoSnippet; import com.ypm.service.PlayListService; -import com.ypm.service.VideosService; +import com.ypm.service.VideoService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; @@ -19,22 +19,28 @@ @RequiredArgsConstructor public class PlayListController { private final PlayListService playListService; - private final VideosService videosService; + private final VideoService videosService; @GetMapping public ResponseEntity> getPlayLists( @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication) throws IOException { - String accessToken = authentication.getAccessToken().getTokenValue(); - return ResponseEntity.ok(playListService.getMyPlayLists(accessToken)); + String accessToken = authentication + .getAccessToken() + .getTokenValue(); + + return ResponseEntity.ok(playListService.getPlayLists(accessToken)); } @GetMapping("/{playlistId}") - public ResponseEntity> getPlayListVideos( + public ResponseEntity> getPlayListVideos( @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, @PathVariable String playlistId) throws IOException { - String accessToken = authentication.getAccessToken().getTokenValue(); + String accessToken = authentication + .getAccessToken() + .getTokenValue(); + return ResponseEntity.ok(videosService.getPlayListVideos(accessToken, playlistId)); } @@ -44,8 +50,26 @@ public ResponseEntity updatePlayListName( @PathVariable String playlistId, @RequestBody PlaylistSnippet dataWithUpdatedTitle) throws IOException { - String accessToken = authentication.getAccessToken().getTokenValue(); + String accessToken = authentication + .getAccessToken() + .getTokenValue(); + String newTitle = dataWithUpdatedTitle.getTitle(); return ResponseEntity.ok(playListService.updatePlayListName(accessToken, playlistId, newTitle)); } + + @PutMapping("/{playlistId}/{targetPlaylistId}") + public ResponseEntity> moveVideos( + @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, + @PathVariable String playlistId, + @PathVariable String targetPlaylistId, + @RequestBody List videosIds) throws IOException { + + String accessToken = authentication + .getAccessToken() + .getTokenValue(); + + return ResponseEntity.ok(videosService.moveVideos(accessToken, playlistId, + targetPlaylistId, videosIds)); + } } diff --git a/src/main/java/com/ypm/controller/VideoController.java b/src/main/java/com/ypm/controller/VideoController.java new file mode 100644 index 0000000..70ffb1d --- /dev/null +++ b/src/main/java/com/ypm/controller/VideoController.java @@ -0,0 +1,31 @@ +package com.ypm.controller; + +import com.ypm.service.VideoService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; + +@RestController +@RequestMapping("/videos") +@RequiredArgsConstructor +public class VideoController { + private final VideoService videosService; + + @DeleteMapping("/{videoId}") + public ResponseEntity deleteVideos( + @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, + @PathVariable String videoId) throws IOException { + + String accessToken = authentication + .getAccessToken() + .getTokenValue(); + + videosService.deleteVideo(accessToken, videoId); + + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/ypm/service/PlayListService.java b/src/main/java/com/ypm/service/PlayListService.java index bc8e9e6..3c04600 100644 --- a/src/main/java/com/ypm/service/PlayListService.java +++ b/src/main/java/com/ypm/service/PlayListService.java @@ -14,14 +14,14 @@ public class PlayListService { private final YouTube youTubeClient; - public List getMyPlayLists(String accessToken) throws IOException { - var request = youTubeClient.playlists().list(List.of("snippet")); - var response = request + public List getPlayLists(String accessToken) throws IOException { + return youTubeClient + .playlists() + .list(List.of("snippet")) .setAccessToken(accessToken) .setMine(true) - .execute(); - - return response.getItems(); + .execute() + .getItems(); } public Playlist updatePlayListName(String accessToken, String playListId, String newTitle) @@ -29,23 +29,25 @@ public Playlist updatePlayListName(String accessToken, String playListId, String Playlist playlistToEdit = getPlayListById(accessToken, playListId); playlistToEdit.getSnippet().setTitle(newTitle); - var request = youTubeClient.playlists().update(List.of("snippet"), playlistToEdit); - return request.setAccessToken(accessToken).execute(); - } + return youTubeClient + .playlists() + .update(List.of("snippet"), playlistToEdit) + .setAccessToken(accessToken) + .execute(); + } public Playlist getPlayListById(String accessToken, String playListId) throws IOException { - var request = youTubeClient.playlists().list(List.of("snippet")); - var response = request + return youTubeClient + .playlists() + .list(List.of("snippet")) + .setId(List.of(playListId)) .setAccessToken(accessToken) .setMine(true) - .execute(); - - return response + .execute() .getItems() .stream() - .filter(playlist -> playlist.getId().equals(playListId)) .findFirst() - .orElseThrow(() -> new RuntimeException("Playlist not found.")); + .orElseThrow(); } } diff --git a/src/main/java/com/ypm/service/VideoService.java b/src/main/java/com/ypm/service/VideoService.java new file mode 100644 index 0000000..9397b88 --- /dev/null +++ b/src/main/java/com/ypm/service/VideoService.java @@ -0,0 +1,83 @@ +package com.ypm.service; + +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.model.PlaylistItem; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class VideoService { + + private final YouTube youTubeClient; + + public List moveVideos(String accessToken, + String playListId, + String targetPlayListId, + List videosIds) throws IOException { + + List videosToMove = getVideos(accessToken, videosIds); + List movedVideos = new ArrayList<>(videosIds.size()); + + for (PlaylistItem video : videosToMove) { + if (isVideoInPlayList(playListId, video)) { + video.getSnippet().setPlaylistId(targetPlayListId); + movedVideos.add(insertVideo(accessToken, video)); + deleteVideo(accessToken, video.getId()); + } + } + + return movedVideos; + } + + public List getVideos(String accessToken, + List videosIds) throws IOException { + + return youTubeClient + .playlistItems() + .list(List.of("snippet")) + .setId(videosIds) + .setAccessToken(accessToken) + .execute() + .getItems(); + } + + public PlaylistItem insertVideo(String accessToken, PlaylistItem playlistItem) throws IOException { + return youTubeClient + .playlistItems() + .insert(List.of("snippet"), playlistItem) + .setAccessToken(accessToken) + .execute(); + } + + public void deleteVideo(String accessToken, String id) throws IOException { + youTubeClient + .playlistItems() + .delete(id) + .setAccessToken(accessToken) + .execute(); + } + + public List getPlayListVideos(String accessToken, String playListId) + throws IOException { + + return youTubeClient + .playlistItems() + .list(List.of("snippet")) + .setPlaylistId(playListId) + .setAccessToken(accessToken) + .execute() + .getItems(); + } + + private boolean isVideoInPlayList(String playListId, PlaylistItem video) { + return video + .getSnippet() + .getPlaylistId() + .equals(playListId); + } +} diff --git a/src/main/java/com/ypm/service/VideosService.java b/src/main/java/com/ypm/service/VideosService.java deleted file mode 100644 index 40f7054..0000000 --- a/src/main/java/com/ypm/service/VideosService.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.ypm.service; - -import com.google.api.services.youtube.YouTube; -import com.google.api.services.youtube.model.VideoSnippet; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.io.IOException; -import java.util.List; - -@Service -@RequiredArgsConstructor -public class VideosService { - - private final YouTube youTubeClient; - - public List getPlayListVideos(String accessToken, String playListId) - throws IOException { - - var request = youTubeClient.playlistItems().list(List.of("snippet")); - var response = request - .setAccessToken(accessToken) - .setPlaylistId(playListId) - .execute(); - - return response - .getItems() - .stream() - .map(item -> new VideoSnippet().setTitle(item.getSnippet().getTitle())) - .toList(); - } -} diff --git a/src/test/java/com/ypm/controller/PlayListControllerTest.java b/src/test/java/com/ypm/controller/PlayListControllerTest.java index 5ca838e..da04e7a 100644 --- a/src/test/java/com/ypm/controller/PlayListControllerTest.java +++ b/src/test/java/com/ypm/controller/PlayListControllerTest.java @@ -1,10 +1,10 @@ package com.ypm.controller; import com.google.api.services.youtube.model.Playlist; +import com.google.api.services.youtube.model.PlaylistItem; import com.google.api.services.youtube.model.PlaylistSnippet; -import com.google.api.services.youtube.model.VideoSnippet; import com.ypm.service.PlayListService; -import com.ypm.service.VideosService; +import com.ypm.service.VideoService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -37,14 +37,14 @@ class PlayListControllerTest { private PlayListService playListService; @MockBean - private VideosService videosService; + private VideoService videosService; @Test void givenCorrectRequest_whenGetPlayLists_thenResponseContainsPlayListName() throws Exception { Playlist playlist = new Playlist(); playlist.setSnippet(new PlaylistSnippet().setTitle("Test Playlist")); List playlists = Collections.singletonList(playlist); - when(playListService.getMyPlayLists(any())).thenReturn(playlists); + when(playListService.getPlayLists(any())).thenReturn(playlists); mockMvc.perform(get("/playlists") .with(oauth2Login() @@ -53,13 +53,14 @@ void givenCorrectRequest_whenGetPlayLists_thenResponseContainsPlayListName() thr .andExpect(jsonPath("$").isArray()) .andExpect(jsonPath("$[0].snippet.title").value("Test Playlist")); - verify(playListService, times(1)).getMyPlayLists(any()); + verify(playListService, times(1)).getPlayLists(any()); } @Test void givenCorrectRequest_whenGetPlayListVideos_thenResponseContainsVideoTitle() throws Exception { - VideoSnippet video = new VideoSnippet().setTitle("Test Video"); - List videos = Collections.singletonList(video); + PlaylistItem video = new PlaylistItem(); + video.getSnippet().setTitle("Video Title"); + List videos = List.of(video); when(videosService.getPlayListVideos(any(), any())).thenReturn(videos); mockMvc.perform(get("/playlists/{playlistId}", "playlistId") diff --git a/src/test/java/com/ypm/controller/VideoControllerTest.java b/src/test/java/com/ypm/controller/VideoControllerTest.java new file mode 100644 index 0000000..8d27e36 --- /dev/null +++ b/src/test/java/com/ypm/controller/VideoControllerTest.java @@ -0,0 +1,40 @@ +package com.ypm.controller; + +import com.ypm.service.VideoService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +public class VideoControllerTest { + @MockBean + private VideoService videosService; + + @Autowired + private ClientRegistrationRepository clientRegistrationRepository; + + @Autowired + private MockMvc mockMvc; + + @Test + void givenCorrectRequest_whenDeleteVideos_thenNoContent() throws Exception { + var login = oauth2Login() + .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")); + + doNothing().when(videosService).deleteVideo(any(), any()); + + mockMvc.perform(delete("/videos/{videoId}", "videoId").with(login)) + .andExpect(status().isNoContent()); + } +} diff --git a/src/test/java/com/ypm/service/YouTubeServiceTest.java b/src/test/java/com/ypm/service/YouTubeServiceTest.java index a3ecbe2..c4c4bb4 100644 --- a/src/test/java/com/ypm/service/YouTubeServiceTest.java +++ b/src/test/java/com/ypm/service/YouTubeServiceTest.java @@ -26,7 +26,7 @@ class YouTubeServiceTest { private PlayListService playListService; @InjectMocks - private VideosService videosService; + private VideoService videosService; @Test void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { @@ -43,7 +43,7 @@ void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { when(playlistsList.setMine(true)).thenReturn(playlistsList); when(playlistsList.execute()).thenReturn(playlistsListResponse); - List result = playListService.getMyPlayLists(accessToken); + List result = playListService.getPlayLists(accessToken); assertEquals(1, result.size()); assertEquals(expectedPlaylist, result.get(0)); @@ -68,9 +68,9 @@ void testGetPlayListVideos() throws IOException { when(playlistItemsList.setPlaylistId(playlistId)).thenReturn(playlistItemsList); when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); - List result = videosService.getPlayListVideos(accessToken, playlistId); + List result = videosService.getPlayListVideos(accessToken, playlistId); assertEquals(1, result.size()); - assertEquals("Video Title", result.get(0).getTitle()); + assertEquals("Video Title", result.get(0).getSnippet().getTitle()); } } From 1d5b5f2518ae83618ca9789c4794eb51e6a94212 Mon Sep 17 00:00:00 2001 From: David Rabko Date: Mon, 1 Apr 2024 16:34:25 +0200 Subject: [PATCH 3/4] Update unit tests --- .../com/ypm/controller/AuthController.java | 1 + .../ypm/controller/PlayListController.java | 7 +- .../com/ypm/controller/VideoController.java | 1 + .../java/com/ypm/service/PlayListService.java | 4 +- .../java/com/ypm/service/VideoService.java | 4 +- .../ypm/controller/AuthControllerTest.java | 8 +- .../controller/PlayListControllerTest.java | 87 ++++++++--- .../ypm/controller/VideoControllerTest.java | 5 +- .../com/ypm/service/PlayListServiceTest.java | 100 ++++++++++++ .../com/ypm/service/VideoServiceTest.java | 145 ++++++++++++++++++ .../com/ypm/service/YouTubeServiceTest.java | 76 --------- 11 files changed, 331 insertions(+), 107 deletions(-) create mode 100644 src/test/java/com/ypm/service/PlayListServiceTest.java create mode 100644 src/test/java/com/ypm/service/VideoServiceTest.java delete mode 100644 src/test/java/com/ypm/service/YouTubeServiceTest.java diff --git a/src/main/java/com/ypm/controller/AuthController.java b/src/main/java/com/ypm/controller/AuthController.java index 256ec87..31fa30f 100644 --- a/src/main/java/com/ypm/controller/AuthController.java +++ b/src/main/java/com/ypm/controller/AuthController.java @@ -10,6 +10,7 @@ @RequestMapping("/auth") @RequiredArgsConstructor public class AuthController { + @GetMapping("/success") public ModelAndView success() { return getModelAndView("success", "Login Success", diff --git a/src/main/java/com/ypm/controller/PlayListController.java b/src/main/java/com/ypm/controller/PlayListController.java index a4c2d3a..3fa654f 100644 --- a/src/main/java/com/ypm/controller/PlayListController.java +++ b/src/main/java/com/ypm/controller/PlayListController.java @@ -18,6 +18,7 @@ @RequestMapping("/playlists") @RequiredArgsConstructor public class PlayListController { + private final PlayListService playListService; private final VideoService videosService; @@ -44,8 +45,8 @@ public ResponseEntity> getPlayListVideos( return ResponseEntity.ok(videosService.getPlayListVideos(accessToken, playlistId)); } - @PutMapping("/{playlistId}/updateTitle") - public ResponseEntity updatePlayListName( + @PutMapping("/{playlistId}") + public ResponseEntity updatePlayListTitle( @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authentication, @PathVariable String playlistId, @RequestBody PlaylistSnippet dataWithUpdatedTitle) throws IOException { @@ -55,7 +56,7 @@ public ResponseEntity updatePlayListName( .getTokenValue(); String newTitle = dataWithUpdatedTitle.getTitle(); - return ResponseEntity.ok(playListService.updatePlayListName(accessToken, playlistId, newTitle)); + return ResponseEntity.ok(playListService.updatePlayListTitle(accessToken, playlistId, newTitle)); } @PutMapping("/{playlistId}/{targetPlaylistId}") diff --git a/src/main/java/com/ypm/controller/VideoController.java b/src/main/java/com/ypm/controller/VideoController.java index 70ffb1d..55869e0 100644 --- a/src/main/java/com/ypm/controller/VideoController.java +++ b/src/main/java/com/ypm/controller/VideoController.java @@ -13,6 +13,7 @@ @RequestMapping("/videos") @RequiredArgsConstructor public class VideoController { + private final VideoService videosService; @DeleteMapping("/{videoId}") diff --git a/src/main/java/com/ypm/service/PlayListService.java b/src/main/java/com/ypm/service/PlayListService.java index 3c04600..df0fb4b 100644 --- a/src/main/java/com/ypm/service/PlayListService.java +++ b/src/main/java/com/ypm/service/PlayListService.java @@ -24,8 +24,8 @@ public List getPlayLists(String accessToken) throws IOException { .getItems(); } - public Playlist updatePlayListName(String accessToken, String playListId, String newTitle) - throws IOException { + public Playlist updatePlayListTitle(String accessToken, String playListId, + String newTitle) throws IOException { Playlist playlistToEdit = getPlayListById(accessToken, playListId); playlistToEdit.getSnippet().setTitle(newTitle); diff --git a/src/main/java/com/ypm/service/VideoService.java b/src/main/java/com/ypm/service/VideoService.java index 9397b88..c43b7b3 100644 --- a/src/main/java/com/ypm/service/VideoService.java +++ b/src/main/java/com/ypm/service/VideoService.java @@ -62,8 +62,8 @@ public void deleteVideo(String accessToken, String id) throws IOException { .execute(); } - public List getPlayListVideos(String accessToken, String playListId) - throws IOException { + public List getPlayListVideos(String accessToken, + String playListId) throws IOException { return youTubeClient .playlistItems() diff --git a/src/test/java/com/ypm/controller/AuthControllerTest.java b/src/test/java/com/ypm/controller/AuthControllerTest.java index 70d23a1..ecd0f61 100644 --- a/src/test/java/com/ypm/controller/AuthControllerTest.java +++ b/src/test/java/com/ypm/controller/AuthControllerTest.java @@ -13,7 +13,8 @@ @SpringBootTest @AutoConfigureMockMvc -public class AuthControllerTest { +class AuthControllerTest { + @Autowired private MockMvc mockMvc; @@ -24,7 +25,7 @@ void givenOAuth2Login_whenAuthSuccess_thenLoginSuccessful() throws Exception { .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.view().name("auth")) .andExpect(MockMvcResultMatchers.model().attribute("type", "success")) - .andExpect(MockMvcResultMatchers.model().attribute("title", "Login Successful")) + .andExpect(MockMvcResultMatchers.model().attribute("title", "Login Success")) .andExpect(MockMvcResultMatchers.model().attribute("message", "Welcome back! You have successfully logged in.")); } @@ -38,7 +39,6 @@ void givenMockUser_whenAuthError_thenLoginError() throws Exception { .andExpect(MockMvcResultMatchers.model().attribute("type", "error")) .andExpect(MockMvcResultMatchers.model().attribute("title", "Login Error")) .andExpect(MockMvcResultMatchers.model().attribute("message", - "Sorry, there was an error with your login credentials. Please try again.")); + "An error occurred while logging in. Please try again.")); } - } diff --git a/src/test/java/com/ypm/controller/PlayListControllerTest.java b/src/test/java/com/ypm/controller/PlayListControllerTest.java index da04e7a..3139cdd 100644 --- a/src/test/java/com/ypm/controller/PlayListControllerTest.java +++ b/src/test/java/com/ypm/controller/PlayListControllerTest.java @@ -1,7 +1,9 @@ package com.ypm.controller; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.api.services.youtube.model.Playlist; import com.google.api.services.youtube.model.PlaylistItem; +import com.google.api.services.youtube.model.PlaylistItemSnippet; import com.google.api.services.youtube.model.PlaylistSnippet; import com.ypm.service.PlayListService; import com.ypm.service.VideoService; @@ -10,6 +12,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.test.web.servlet.MockMvc; @@ -20,56 +23,104 @@ import static org.mockito.Mockito.*; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @SpringBootTest @AutoConfigureMockMvc class PlayListControllerTest { + @MockBean + private PlayListService playListService; + + @MockBean + private VideoService videosService; + @Autowired private ClientRegistrationRepository clientRegistrationRepository; @Autowired private MockMvc mockMvc; - @MockBean - private PlayListService playListService; - - @MockBean - private VideoService videosService; + @Autowired + private ObjectMapper objectMapper; @Test void givenCorrectRequest_whenGetPlayLists_thenResponseContainsPlayListName() throws Exception { + var login = oauth2Login() + .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")); + Playlist playlist = new Playlist(); playlist.setSnippet(new PlaylistSnippet().setTitle("Test Playlist")); List playlists = Collections.singletonList(playlist); + when(playListService.getPlayLists(any())).thenReturn(playlists); - mockMvc.perform(get("/playlists") - .with(oauth2Login() - .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")))) + mockMvc.perform(get("/playlists").with(login)) .andExpect(status().isOk()) - .andExpect(jsonPath("$").isArray()) - .andExpect(jsonPath("$[0].snippet.title").value("Test Playlist")); + .andExpect(content().json(objectMapper.writeValueAsString(playlists))); verify(playListService, times(1)).getPlayLists(any()); } @Test void givenCorrectRequest_whenGetPlayListVideos_thenResponseContainsVideoTitle() throws Exception { + var login = oauth2Login() + .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")); + PlaylistItem video = new PlaylistItem(); - video.getSnippet().setTitle("Video Title"); + video.setSnippet(new PlaylistItemSnippet().setTitle("New Title")); List videos = List.of(video); + when(videosService.getPlayListVideos(any(), any())).thenReturn(videos); - mockMvc.perform(get("/playlists/{playlistId}", "playlistId") - .with(oauth2Login() - .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")))) + mockMvc.perform(get("/playlists/{playlistId}", "someId").with(login)) .andExpect(status().isOk()) - .andExpect(jsonPath("$").isArray()) - .andExpect(jsonPath("$[0].title").value("Test Video")); + .andExpect(content().json(objectMapper.writeValueAsString(videos))); verify(videosService, times(1)).getPlayListVideos(any(), any()); } + + @Test + void givenCorrectRequest_whenUpdatePlayListTitle_thenResponseContainsUpdatedTitle() throws Exception { + var login = oauth2Login() + .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")); + + Playlist playlist = new Playlist(); + playlist.setSnippet(new PlaylistSnippet().setTitle("New Title")); + + when(playListService.updatePlayListTitle(any(), any(), any())).thenReturn(playlist); + + mockMvc.perform(put("/playlists/{playlistId}", "someId") + .with(login) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(playlist))) + .andExpect(status().isOk()) + .andExpect(content().json(objectMapper.writeValueAsString(playlist))); + + verify(playListService, times(1)) + .updatePlayListTitle(any(), any(), any()); + } + + @Test + void givenCorrectRequest_whenMoveVideos_thenResponseContainsMovedVideos() throws Exception { + var login = oauth2Login() + .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("google")); + + List videosIds = List.of("videoId1", "videoId2"); + List videos = List.of(new PlaylistItem(), new PlaylistItem()); + + when(videosService.moveVideos(any(), any(), any(), any())).thenReturn(videos); + + mockMvc.perform(put("/playlists/{playlistId}/{targetPlaylistId}", + "someId", "targetId") + .with(login) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(videosIds))) + .andExpect(status().isOk()) + .andExpect(content().json(objectMapper.writeValueAsString(videos))); + + verify(videosService, times(1)) + .moveVideos(any(), any(), any(), any()); + } } diff --git a/src/test/java/com/ypm/controller/VideoControllerTest.java b/src/test/java/com/ypm/controller/VideoControllerTest.java index 8d27e36..1b0a5cd 100644 --- a/src/test/java/com/ypm/controller/VideoControllerTest.java +++ b/src/test/java/com/ypm/controller/VideoControllerTest.java @@ -17,7 +17,8 @@ @SpringBootTest @AutoConfigureMockMvc -public class VideoControllerTest { +class VideoControllerTest { + @MockBean private VideoService videosService; @@ -34,7 +35,7 @@ void givenCorrectRequest_whenDeleteVideos_thenNoContent() throws Exception { doNothing().when(videosService).deleteVideo(any(), any()); - mockMvc.perform(delete("/videos/{videoId}", "videoId").with(login)) + mockMvc.perform(delete("/videos/{videoId}", "someId").with(login)) .andExpect(status().isNoContent()); } } diff --git a/src/test/java/com/ypm/service/PlayListServiceTest.java b/src/test/java/com/ypm/service/PlayListServiceTest.java new file mode 100644 index 0000000..7bced3a --- /dev/null +++ b/src/test/java/com/ypm/service/PlayListServiceTest.java @@ -0,0 +1,100 @@ +package com.ypm.service; + +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.model.Playlist; +import com.google.api.services.youtube.model.PlaylistListResponse; +import com.google.api.services.youtube.model.PlaylistSnippet; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.IOException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@SpringBootTest +public class PlayListServiceTest { + + private final String accessToken = + "ey.aphktnp.eyJzdWIiOiJ0ZXN0IiwibmFtZSI6IlRlc3QiLCJpYXQiOjE2MjMwNjMwMjJ9"; + + @Mock + private YouTube youTubeClient; + + @InjectMocks + private PlayListService playListService; + + @Test + void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { + var playlists = mock(YouTube.Playlists.class); + var playlistsList = mock(YouTube.Playlists.List.class); + var expectedPlaylist = new Playlist(); + expectedPlaylist.setSnippet(new PlaylistSnippet().setTitle("Playlist Title")); + var playlistsListResponse = new PlaylistListResponse() + .setItems(List.of(expectedPlaylist)); + + when(youTubeClient.playlists()).thenReturn(playlists); + when(playlists.list(List.of("snippet"))).thenReturn(playlistsList); + when(playlistsList.setAccessToken(accessToken)).thenReturn(playlistsList); + when(playlistsList.setMine(true)).thenReturn(playlistsList); + when(playlistsList.execute()).thenReturn(playlistsListResponse); + + List result = playListService.getPlayLists(accessToken); + + assertEquals(1, result.size()); + assertEquals(expectedPlaylist, result.get(0)); + assertEquals("Playlist Title", result.get(0).getSnippet().getTitle()); + } + + @Test + void givenCorrectData_whenUpdatePlayListTitle_thenPlayListTitleUpdated() throws IOException { + var playlists = mock(YouTube.Playlists.class); + var playlistsList = mock(YouTube.Playlists.List.class); + var playlistUpdate = mock(YouTube.Playlists.Update.class); + var expectedPlaylist = new Playlist(); + expectedPlaylist.setSnippet(new PlaylistSnippet().setTitle("Playlist Title")); + var playlistsListResponse = new PlaylistListResponse() + .setItems(List.of(expectedPlaylist)); + + when(youTubeClient.playlists()).thenReturn(playlists); + when(playlists.list(List.of("snippet"))).thenReturn(playlistsList); + when(playlistsList.setAccessToken(accessToken)).thenReturn(playlistsList); + when(playlistsList.setMine(true)).thenReturn(playlistsList); + when(playlistsList.setId(any())).thenReturn(playlistsList); + when(playlistsList.execute()).thenReturn(playlistsListResponse); + when(playlists.update(List.of("snippet"), expectedPlaylist)).thenReturn(playlistUpdate); + when(playlistUpdate.setAccessToken(accessToken)).thenReturn(playlistUpdate); + when(playlistUpdate.execute()).thenReturn(expectedPlaylist); + + Playlist result = playListService.updatePlayListTitle(accessToken, "playlistId", "New Title"); + + assertEquals("New Title", result.getSnippet().getTitle()); + } + + @Test + void givenCorrectData_whenGetPlayListById_thenPlayListFound() throws IOException { + var playlists = mock(YouTube.Playlists.class); + var playlistsList = mock(YouTube.Playlists.List.class); + var expectedPlaylist = new Playlist(); + expectedPlaylist.setSnippet(new PlaylistSnippet().setTitle("Playlist Title")); + var playlistsListResponse = new PlaylistListResponse() + .setItems(List.of(expectedPlaylist)); + + when(youTubeClient.playlists()).thenReturn(playlists); + when(playlists.list(List.of("snippet"))).thenReturn(playlistsList); + when(playlistsList.setAccessToken(accessToken)).thenReturn(playlistsList); + when(playlistsList.setMine(true)).thenReturn(playlistsList); + when(playlistsList.setId(List.of("playlistId"))).thenReturn(playlistsList); + when(playlistsList.execute()).thenReturn(playlistsListResponse); + + Playlist result = playListService.getPlayListById(accessToken, "playlistId"); + + assertEquals(expectedPlaylist, result); + assertEquals("Playlist Title", result.getSnippet().getTitle()); + } +} diff --git a/src/test/java/com/ypm/service/VideoServiceTest.java b/src/test/java/com/ypm/service/VideoServiceTest.java new file mode 100644 index 0000000..2e9a135 --- /dev/null +++ b/src/test/java/com/ypm/service/VideoServiceTest.java @@ -0,0 +1,145 @@ +package com.ypm.service; + +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.model.PlaylistItem; +import com.google.api.services.youtube.model.PlaylistItemListResponse; +import com.google.api.services.youtube.model.PlaylistItemSnippet; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.IOException; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@SpringBootTest +public class VideoServiceTest { + + private final String accessToken = + "ey.aphktnp.eyJzdWIiOiJ0ZXN0IiwibmFtZSI6IlRlc3QiLCJpYXQiOjE2MjMwNjMwMjJ9"; + + @Mock + private YouTube youTubeClient; + + @InjectMocks + private VideoService videoService; + + @Test + void givenExistingPlayList_whenGetPlayListVideos_thenPlayListVideosReturned() throws IOException { + String playlistId = "asdsdta_hdfyZSDF"; + var playlistItems = mock(YouTube.PlaylistItems.class); + var playlistItemsList = mock(YouTube.PlaylistItems.List.class); + var expectedPlaylistItem = new PlaylistItem(); + var snippet = new PlaylistItemSnippet(); + snippet.setTitle("Video Title"); + expectedPlaylistItem.setSnippet(snippet); + var playlistItemsListResponse = new PlaylistItemListResponse() + .setItems(List.of(expectedPlaylistItem)); + + when(youTubeClient.playlistItems()).thenReturn(playlistItems); + when(playlistItems.list(List.of("snippet"))).thenReturn(playlistItemsList); + when(playlistItemsList.setAccessToken(accessToken)).thenReturn(playlistItemsList); + when(playlistItemsList.setPlaylistId(playlistId)).thenReturn(playlistItemsList); + when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); + + List result = videoService.getPlayListVideos(accessToken, playlistId); + + assertEquals(1, result.size()); + assertEquals("Video Title", result.get(0).getSnippet().getTitle()); + } + + @Test + void givenExistingVideos_whenGetVideos_thenVideosReturned() throws IOException { + List videosIds = List.of("videoId1", "videoId2"); + var playlistItems = mock(YouTube.PlaylistItems.class); + var playlistItemsList = mock(YouTube.PlaylistItems.List.class); + var expectedPlaylistItem = new PlaylistItem(); + var snippet = new PlaylistItemSnippet(); + snippet.setTitle("Video Title"); + expectedPlaylistItem.setSnippet(snippet); + var playlistItemsListResponse = new PlaylistItemListResponse() + .setItems(List.of(expectedPlaylistItem, expectedPlaylistItem)); + + when(youTubeClient.playlistItems()).thenReturn(playlistItems); + when(playlistItems.list(List.of("snippet"))).thenReturn(playlistItemsList); + when(playlistItemsList.setAccessToken(accessToken)).thenReturn(playlistItemsList); + when(playlistItemsList.setId(videosIds)).thenReturn(playlistItemsList); + when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); + + List result = videoService.getVideos(accessToken, videosIds); + + assertEquals(2, result.size()); + assertEquals("Video Title", result.get(0).getSnippet().getTitle()); + } + + @Test + void givenCorrectVideoData_whenInsertVideo_thenInsertedVideoReturned() throws IOException { + var playlistItems = mock(YouTube.PlaylistItems.class); + var playlistItemsInsert = mock(YouTube.PlaylistItems.Insert.class); + var expectedPlaylistItem = new PlaylistItem(); + var snippet = new PlaylistItemSnippet(); + snippet.setTitle("Video Title"); + expectedPlaylistItem.setSnippet(snippet); + + when(youTubeClient.playlistItems()).thenReturn(playlistItems); + when(playlistItems.insert(List.of("snippet"), expectedPlaylistItem)).thenReturn(playlistItemsInsert); + when(playlistItemsInsert.setAccessToken(accessToken)).thenReturn(playlistItemsInsert); + when(playlistItemsInsert.execute()).thenReturn(expectedPlaylistItem); + + PlaylistItem result = videoService.insertVideo(accessToken, expectedPlaylistItem); + + assertEquals("Video Title", result.getSnippet().getTitle()); + } + + @Test + void givenExistingVideo_whenDeleteVideo_thenNotException() throws IOException { + var playlistItems = mock(YouTube.PlaylistItems.class); + var playlistItemsDelete = mock(YouTube.PlaylistItems.Delete.class); + String videoId = "asdsdta_hdfyZSDF"; + + when(youTubeClient.playlistItems()).thenReturn(playlistItems); + when(playlistItems.delete(videoId)).thenReturn(playlistItemsDelete); + when(playlistItemsDelete.setAccessToken(accessToken)).thenReturn(playlistItemsDelete); + + videoService.deleteVideo(accessToken, videoId); + + verify(playlistItems, times(1)).delete(videoId); + } + + @Test + void givenExistingVideos_whenMoveVideos_thenMovedVideosReturned() throws IOException { + String playListId = "asdsdta_hdfyZSDF"; + String targetPlayListId = "asdsdta_hdfyZSDF"; + List videosIds = List.of("videoId1", "videoId2"); + var playlistItems = mock(YouTube.PlaylistItems.class); + var playlistItemsList = mock(YouTube.PlaylistItems.List.class); + var playlistItemsInsert = mock(YouTube.PlaylistItems.Insert.class); + var playlistItemsDelete = mock(YouTube.PlaylistItems.Delete.class); + var expectedPlaylistItem = new PlaylistItem(); + var snippet = new PlaylistItemSnippet(); + snippet.setPlaylistId("asdsdta_hdfyZSDF"); + snippet.setTitle("Video Title"); + expectedPlaylistItem.setSnippet(snippet); + var playlistItemsListResponse = new PlaylistItemListResponse() + .setItems(List.of(expectedPlaylistItem, expectedPlaylistItem)); + + when(youTubeClient.playlistItems()).thenReturn(playlistItems); + when(playlistItems.list(List.of("snippet"))).thenReturn(playlistItemsList); + when(playlistItems.insert(List.of("snippet"), expectedPlaylistItem)).thenReturn(playlistItemsInsert); + when(playlistItems.delete(any())).thenReturn(playlistItemsDelete); + when(playlistItemsList.setAccessToken(accessToken)).thenReturn(playlistItemsList); + when(playlistItemsList.setId(videosIds)).thenReturn(playlistItemsList); + when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); + when(playlistItemsInsert.execute()).thenReturn(expectedPlaylistItem); + when(playlistItemsInsert.setAccessToken(accessToken)).thenReturn(playlistItemsInsert); + when(playlistItemsDelete.setAccessToken(accessToken)).thenReturn(playlistItemsDelete); + + List result = videoService.moveVideos(accessToken, playListId, targetPlayListId, videosIds); + + assertEquals(2, result.size()); + assertEquals("Video Title", result.get(0).getSnippet().getTitle()); + } +} diff --git a/src/test/java/com/ypm/service/YouTubeServiceTest.java b/src/test/java/com/ypm/service/YouTubeServiceTest.java deleted file mode 100644 index c4c4bb4..0000000 --- a/src/test/java/com/ypm/service/YouTubeServiceTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.ypm.service; - -import com.google.api.services.youtube.YouTube; -import com.google.api.services.youtube.model.*; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.boot.test.context.SpringBootTest; - -import java.io.IOException; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@SpringBootTest -class YouTubeServiceTest { - private final String accessToken = - "ey.aphktnp.eyJzdWIiOiJ0ZXN0IiwibmFtZSI6IlRlc3QiLCJpYXQiOjE2MjMwNjMwMjJ9"; - - @Mock - private YouTube youTubeClient; - - @InjectMocks - private PlayListService playListService; - - @InjectMocks - private VideoService videosService; - - @Test - void givenCorrectData_whenGetPlayLists_thenPlaylistsFound() throws IOException { - var playlists = mock(YouTube.Playlists.class); - var playlistsList = mock(YouTube.Playlists.List.class); - var expectedPlaylist = new Playlist(); - expectedPlaylist.setSnippet(new PlaylistSnippet().setTitle("Playlist Title")); - var playlistsListResponse = new PlaylistListResponse() - .setItems(List.of(expectedPlaylist)); - - when(youTubeClient.playlists()).thenReturn(playlists); - when(playlists.list(List.of("snippet"))).thenReturn(playlistsList); - when(playlistsList.setAccessToken(accessToken)).thenReturn(playlistsList); - when(playlistsList.setMine(true)).thenReturn(playlistsList); - when(playlistsList.execute()).thenReturn(playlistsListResponse); - - List result = playListService.getPlayLists(accessToken); - - assertEquals(1, result.size()); - assertEquals(expectedPlaylist, result.get(0)); - assertEquals("Playlist Title", result.get(0).getSnippet().getTitle()); - } - - @Test - void testGetPlayListVideos() throws IOException { - String playlistId = "asdsdta_hdfyZSDF"; - var playlistItems = mock(YouTube.PlaylistItems.class); - var playlistItemsList = mock(YouTube.PlaylistItems.List.class); - var expectedPlaylistItem = new PlaylistItem(); - var snippet = new PlaylistItemSnippet(); - snippet.setTitle("Video Title"); - expectedPlaylistItem.setSnippet(snippet); - var playlistItemsListResponse = new PlaylistItemListResponse() - .setItems(List.of(expectedPlaylistItem)); - - when(youTubeClient.playlistItems()).thenReturn(playlistItems); - when(playlistItems.list(List.of("snippet"))).thenReturn(playlistItemsList); - when(playlistItemsList.setAccessToken(accessToken)).thenReturn(playlistItemsList); - when(playlistItemsList.setPlaylistId(playlistId)).thenReturn(playlistItemsList); - when(playlistItemsList.execute()).thenReturn(playlistItemsListResponse); - - List result = videosService.getPlayListVideos(accessToken, playlistId); - - assertEquals(1, result.size()); - assertEquals("Video Title", result.get(0).getSnippet().getTitle()); - } -} From 930cc746c7c5fd5132d4e7fc20fadf08c923d941 Mon Sep 17 00:00:00 2001 From: David Rabko Date: Mon, 1 Apr 2024 22:44:55 +0200 Subject: [PATCH 4/4] Fix getPlayListById --- src/main/java/com/ypm/service/PlayListService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ypm/service/PlayListService.java b/src/main/java/com/ypm/service/PlayListService.java index df0fb4b..e7c012c 100644 --- a/src/main/java/com/ypm/service/PlayListService.java +++ b/src/main/java/com/ypm/service/PlayListService.java @@ -43,7 +43,6 @@ public Playlist getPlayListById(String accessToken, String playListId) throws IO .list(List.of("snippet")) .setId(List.of(playListId)) .setAccessToken(accessToken) - .setMine(true) .execute() .getItems() .stream()