diff --git a/.github/workflows/trivy_scan.yml b/.github/workflows/trivy_scan.yml index cc295d8af..0986e7ecc 100644 --- a/.github/workflows/trivy_scan.yml +++ b/.github/workflows/trivy_scan.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v5 - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@0.32.0 + uses: aquasecurity/trivy-action@0.33.0 with: scan-type: 'fs' format: 'sarif' diff --git a/airsonic-main/pom.xml b/airsonic-main/pom.xml index 80f842ea5..e9306e210 100644 --- a/airsonic-main/pom.xml +++ b/airsonic-main/pom.xml @@ -52,7 +52,7 @@ io.dropwizard.metrics metrics-jmx - 4.2.33 + 4.2.35 diff --git a/airsonic-main/src/main/java/org/airsonic/player/ajax/PlaylistWSController.java b/airsonic-main/src/main/java/org/airsonic/player/ajax/PlaylistWSController.java index 6c10ff93c..e42d13c2a 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/ajax/PlaylistWSController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/ajax/PlaylistWSController.java @@ -1,13 +1,9 @@ package org.airsonic.player.ajax; import org.airsonic.player.domain.MediaFile; -import org.airsonic.player.domain.MusicFolder; -import org.airsonic.player.domain.Player; import org.airsonic.player.domain.Playlist; import org.airsonic.player.i18n.LocaleResolver; import org.airsonic.player.service.MediaFileService; -import org.airsonic.player.service.MediaFolderService; -import org.airsonic.player.service.PlayerService; import org.airsonic.player.service.PlaylistService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.DestinationVariable; @@ -26,7 +22,6 @@ import java.util.List; import java.util.Locale; import java.util.Objects; -import java.util.ResourceBundle; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -38,10 +33,6 @@ public class PlaylistWSController { @Autowired private PlaylistService playlistService; @Autowired - private MediaFolderService mediaFolderService; - @Autowired - private PlayerService playerService; - @Autowired private LocaleResolver localeResolver; @SubscribeMapping("/readable") @@ -55,66 +46,34 @@ public List getWritablePlaylists(Principal p) { return playlistService.getWritablePlaylistsForUser(p.getName()); } - /** - * Creates a playlist and broadcasts it to all users that have access to it. - * - * @param playlist the playlist to create - * @return the id of the created playlist - */ - private Playlist createPlaylist(String name, boolean shared, String username) { - Playlist result = playlistService.createPlaylist(name, shared, username); - playlistService.broadcast(result); - return result; - } - @MessageMapping("/create/empty") @SendToUser(broadcast = false) public int createEmptyPlaylist(Principal p) { Locale locale = localeResolver.resolveLocale(p.getName()); DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocale(locale); Instant now = Instant.now(); - Playlist result = createPlaylist(dateFormat.format(now.atZone(ZoneId.systemDefault())), false, p.getName()); + Playlist result = playlistService.createPlaylist(dateFormat.format(now.atZone(ZoneId.systemDefault())), false, p.getName()); + playlistService.broadcast(result); return result.getId(); } @MessageMapping("/create/starred") @SendToUser(broadcast = false) public int createPlaylistForStarredSongs(Principal p) { - Locale locale = localeResolver.resolveLocale(p.getName()); - DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocale(locale); - - ResourceBundle bundle = ResourceBundle.getBundle("org.airsonic.player.i18n.ResourceBundle", locale); - Instant now = Instant.now(); - String name = bundle.getString("top.starred") + " " + dateFormat.format(now.atZone(ZoneId.systemDefault())); String username = p.getName(); - - Playlist result = createPlaylist(name, false, username); - List musicFolders = mediaFolderService.getMusicFoldersForUser(username); - List songs = mediaFileService.getStarredSongs(0, Integer.MAX_VALUE, username, musicFolders); - Integer playlistId = result.getId(); - playlistService.setFilesInPlaylist(playlistId, songs); + Locale locale = localeResolver.resolveLocale(username); + Integer playlistId = playlistService.createPlaylistForStarredSongs(username, locale); playlistService.broadcastFileChange(playlistId, false, true); - return result.getId(); + return playlistId; } @MessageMapping("/create/playqueue") @SendToUser(broadcast = false) public int createPlaylistForPlayQueue(Principal p, Integer playerId) throws Exception { - Player player = playerService.getPlayerById(playerId); - Locale locale = localeResolver.resolveLocale(p.getName()); - DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocale(locale); - - Instant now = Instant.now(); - Playlist playlist = new Playlist(); - playlist.setUsername(p.getName()); - playlist.setShared(false); - playlist.setName(dateFormat.format(now.atZone(ZoneId.systemDefault()))); - - Playlist result = createPlaylist(dateFormat.format(now.atZone(ZoneId.systemDefault())), false, p.getName()); - Integer playlistId = result.getId(); - playlistService.setFilesInPlaylist(playlistId, player.getPlayQueue().getFiles()); + String username = p.getName(); + Locale locale = localeResolver.resolveLocale(username); + Integer playlistId = playlistService.createPlaylistForPlayQueue(playerId, username, locale); playlistService.broadcastFileChange(playlistId, false, true); - return playlistId; } diff --git a/airsonic-main/src/main/java/org/airsonic/player/repository/PlaylistMediaFileRepository.java b/airsonic-main/src/main/java/org/airsonic/player/repository/PlaylistMediaFileRepository.java index 9aa43a626..12f8cbd60 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/repository/PlaylistMediaFileRepository.java +++ b/airsonic-main/src/main/java/org/airsonic/player/repository/PlaylistMediaFileRepository.java @@ -1,9 +1,40 @@ +/* + This file is part of Airsonic. + + Airsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Airsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Airsonic. If not, see . + + Copyright 2025 (C) Y.Tory + */ package org.airsonic.player.repository; +import org.airsonic.player.domain.MediaFile; import org.airsonic.player.domain.PlaylistMediaFile; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface PlaylistMediaFileRepository extends JpaRepository { + + @Query(""" + select pmf.mediaFile + from PlaylistMediaFile pmf + where pmf.playlist.id = :playlistId + order by pmf.orderIndex + """) + List findMediaFilesByPlaylistId(@Param("playlistId") Integer playlistId); } diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/PlaylistService.java b/airsonic-main/src/main/java/org/airsonic/player/service/PlaylistService.java index 50606571d..36ca71639 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/PlaylistService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/PlaylistService.java @@ -20,10 +20,13 @@ package org.airsonic.player.service; import org.airsonic.player.domain.MediaFile; +import org.airsonic.player.domain.MusicFolder; import org.airsonic.player.domain.PlayQueue; +import org.airsonic.player.domain.Player; import org.airsonic.player.domain.Playlist; import org.airsonic.player.domain.PlaylistMediaFile; import org.airsonic.player.domain.User; +import org.airsonic.player.repository.PlaylistMediaFileRepository; import org.airsonic.player.repository.PlaylistRepository; import org.airsonic.player.repository.UserRepository; import org.airsonic.player.service.cache.PlaylistCache; @@ -31,7 +34,6 @@ import org.airsonic.player.util.LambdaUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,6 +42,9 @@ import jakarta.annotation.Nonnull; import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -55,14 +60,34 @@ public class PlaylistService { private static final Logger LOG = LoggerFactory.getLogger(PlaylistService.class); - @Autowired - private UserRepository userRepository; - @Autowired - private PlaylistRepository playlistRepository; - @Autowired - private AsyncWebSocketClient asyncWebSocketClient; - @Autowired - private PlaylistCache playlistCache; + private final UserRepository userRepository; + private final PlaylistRepository playlistRepository; + private final AsyncWebSocketClient asyncWebSocketClient; + private final PlaylistCache playlistCache; + private final PlaylistMediaFileRepository playlistMediaFileRepository; + private final MediaFileService mediaFileService; + private final MediaFolderService mediaFolderService; + private final PlayerService playerService; + + public PlaylistService( + UserRepository userRepository, + PlaylistRepository playlistRepository, + AsyncWebSocketClient asyncWebSocketClient, + PlaylistCache playlistCache, + PlaylistMediaFileRepository playlistMediaFileRepository, + PlayerService playerService, + MediaFolderService mediaFolderService, + MediaFileService mediaFileService + ) { + this.userRepository = userRepository; + this.playlistRepository = playlistRepository; + this.asyncWebSocketClient = asyncWebSocketClient; + this.playlistCache = playlistCache; + this.playlistMediaFileRepository = playlistMediaFileRepository; + this.playerService = playerService; + this.mediaFolderService = mediaFolderService; + this.mediaFileService = mediaFileService; + } /** @@ -142,6 +167,7 @@ public List getPlaylistUsers(Integer playlistId) { return result; } + @Transactional(readOnly = true) public List getFilesInPlaylist(int id) { return getFilesInPlaylist(id, false); } @@ -149,18 +175,10 @@ public List getFilesInPlaylist(int id) { @Transactional(readOnly = true) public List getFilesInPlaylist(int id, boolean includeNotPresent) { - return playlistRepository.findById(id).map(p -> { - return p.getPlaylistMediaFiles().stream() - .map(PlaylistMediaFile::getMediaFile) + return playlistMediaFileRepository.findMediaFilesByPlaylistId(id).stream() .filter(Objects::nonNull) .filter(x -> x.isPresent() || includeNotPresent) .collect(Collectors.toList()); - }).orElseGet( - () -> { - LOG.warn("Playlist {} not found", id); - return new ArrayList<>(); - } - ); } private List filterNoDurationFiles(List files) { @@ -189,7 +207,6 @@ public Playlist setFilesInPlaylist(int id, List files) { }); } - private Playlist setFilesInPlaylist(Playlist playlist, List files) { List filteredFiles = filterNoDurationFiles(files); @@ -431,6 +448,48 @@ public void broadcastFileChange(Integer id, boolean isShared, boolean filesChang }); } + /** + * Creates a new playlist for the specified play queue. + * + * @param playerId the ID of the player + * @param username the username of the user creating the playlist + * @param locale the locale to use for formatting + * @return the ID of the created playlist + */ + @Transactional + public Integer createPlaylistForPlayQueue(@Nonnull Integer playerId, @Nonnull String username, Locale locale) { + DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocale(locale); + Instant now = Instant.now(); + String name = dateFormat.format(now.atZone(ZoneId.systemDefault())); + + Playlist playlist = createPlaylist(name, false, username); + broadcast(playlist); + + Player player = playerService.getPlayerById(playerId); + playlist = setFilesInPlaylist(playlist, player.getPlayQueue().getFiles()); + + playlistRepository.saveAndFlush(playlist); + return playlist.getId(); + } + + @Transactional + public Integer createPlaylistForStarredSongs(@Nonnull String username, Locale locale) { + + DateTimeFormatter dateFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocale(locale); + ResourceBundle bundle = ResourceBundle.getBundle("org.airsonic.player.i18n.ResourceBundle", locale); + Instant now = Instant.now(); + String name = bundle.getString("top.starred") + " " + dateFormat.format(now.atZone(ZoneId.systemDefault())); + + Playlist playlist = createPlaylist(name, false, username); + broadcast(playlist); + + List musicFolders = mediaFolderService.getMusicFoldersForUser(username); + List musicFiles = mediaFileService.getStarredSongs(0, Integer.MAX_VALUE, username, musicFolders); + setFilesInPlaylist(playlist, musicFiles); + Integer playlistId = playlist.getId(); + return playlistId; + } + public static class BroadcastedPlaylist extends Playlist { private final boolean filesChanged; diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/StreamService.java b/airsonic-main/src/main/java/org/airsonic/player/service/StreamService.java new file mode 100644 index 000000000..0aba3c717 --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/service/StreamService.java @@ -0,0 +1,8 @@ +package org.airsonic.player.service; + +import org.springframework.stereotype.Service; + +@Service +public class StreamService { + +} \ No newline at end of file diff --git a/airsonic-main/src/test/java/org/airsonic/player/repository/PlaylistMediaFileRepositoryTest.java b/airsonic-main/src/test/java/org/airsonic/player/repository/PlaylistMediaFileRepositoryTest.java new file mode 100644 index 000000000..e55402fb7 --- /dev/null +++ b/airsonic-main/src/test/java/org/airsonic/player/repository/PlaylistMediaFileRepositoryTest.java @@ -0,0 +1,172 @@ +/* + This file is part of Airsonic. + + Airsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Airsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Airsonic. If not, see . + + Copyright 2025 (C) Y.Tory + */ +package org.airsonic.player.repository; + +import org.airsonic.player.domain.MediaFile; +import org.airsonic.player.domain.MediaFile.MediaType; +import org.airsonic.player.domain.MusicFolder; +import org.airsonic.player.domain.MusicFolder.Type; +import org.airsonic.player.domain.Playlist; +import org.airsonic.player.domain.PlaylistMediaFile; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import jakarta.transaction.Transactional; + +import java.nio.file.Path; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Transactional +@SpringBootTest +class PlaylistMediaFileRepositoryTest { + + @Autowired + private PlaylistMediaFileRepository playlistMediaFileRepository; + + @Autowired + private PlaylistRepository playlistRepository; + @Autowired + private MusicFolderRepository musicFolderRepository; + + @Autowired + private MediaFileRepository mediaFileRepository; + + @TempDir + private static Path tempDir; + + @BeforeAll + public static void setUp() { + System.setProperty("airsonic.home", tempDir.toString()); + } + + @TempDir + private Path tempMusicDir; + + @Test + public void testGetMediaFilesByRelativePathAndFolderId() { + // prepare folder + MusicFolder testFolder = new MusicFolder(tempMusicDir, "name", Type.MEDIA, true, + Instant.now().truncatedTo(ChronoUnit.MICROS)); + musicFolderRepository.save(testFolder); + // prepare MediaFile + MediaFile baseFile = new MediaFile(); + baseFile.setFolder(testFolder); + baseFile.setPath("test.wav"); + baseFile.setMediaType(MediaType.MUSIC); + baseFile.setIndexPath("test.cue"); + baseFile.setStartPosition(MediaFile.NOT_INDEXED); + baseFile.setCreated(Instant.now()); + baseFile.setChanged(Instant.now()); + baseFile.setLastScanned(Instant.now()); + baseFile.setChildrenLastUpdated(Instant.now()); + mediaFileRepository.save(baseFile); + // prepare playlist + Playlist playlist = new Playlist( + "admin", false, "Test Playlist", "A test playlist", 1, + 300.0, Instant.now(), Instant.now(), "importedFromTest"); + playlistRepository.save(playlist); + + // relation + PlaylistMediaFile pmf = new PlaylistMediaFile(); + pmf.setPlaylist(playlist); + pmf.setMediaFile(baseFile); + pmf.setOrderIndex(1); + playlistMediaFileRepository.save(pmf); + + // execute + List result = playlistMediaFileRepository.findMediaFilesByPlaylistId(playlist.getId()); + + assertEquals(1, result.size()); + assertEquals(baseFile, result.get(0)); + + } + + @Test + @DisplayName("findMediaFilesByPlaylistId returns media files in order for given playlist") + void testFindMediaFilesByPlaylistId() { + + Playlist playlist = new Playlist( + "admin", false, "Test Playlist", "A test playlist", 1, + 300.0, Instant.now(), Instant.now(), "importedFromTest"); + playlist = playlistRepository.save(playlist); + + // prepare folder + MusicFolder testFolder = new MusicFolder(tempMusicDir, "name", Type.MEDIA, true, + Instant.now().truncatedTo(ChronoUnit.MICROS)); + musicFolderRepository.save(testFolder); + // prepare MediaFile + MediaFile baseFile = new MediaFile(); + baseFile.setFolder(testFolder); + baseFile.setPath("test.wav"); + baseFile.setMediaType(MediaType.MUSIC); + baseFile.setIndexPath("test.cue"); + baseFile.setStartPosition(MediaFile.NOT_INDEXED); + baseFile.setCreated(Instant.now()); + baseFile.setChanged(Instant.now()); + baseFile.setLastScanned(Instant.now()); + baseFile.setChildrenLastUpdated(Instant.now()); + mediaFileRepository.save(baseFile); + + MediaFile baseFile2 = new MediaFile(); + baseFile2.setFolder(testFolder); + baseFile2.setPath("test2.wav"); + baseFile2.setMediaType(MediaType.MUSIC); + baseFile2.setIndexPath("test2.cue"); + baseFile2.setStartPosition(MediaFile.NOT_INDEXED); + baseFile2.setCreated(Instant.now()); + baseFile2.setChanged(Instant.now()); + baseFile2.setLastScanned(Instant.now()); + baseFile2.setChildrenLastUpdated(Instant.now()); + mediaFileRepository.save(baseFile2); + + PlaylistMediaFile pmf1 = new PlaylistMediaFile(); + pmf1.setPlaylist(playlist); + pmf1.setMediaFile(baseFile); + pmf1.setOrderIndex(2); + + PlaylistMediaFile pmf2 = new PlaylistMediaFile(); + pmf2.setPlaylist(playlist); + pmf2.setMediaFile(baseFile2); + pmf2.setOrderIndex(1); + + playlistMediaFileRepository.save(pmf1); + playlistMediaFileRepository.save(pmf2); + + List result = playlistMediaFileRepository.findMediaFilesByPlaylistId(playlist.getId()); + + assertEquals(2, result.size()); + assertEquals(baseFile2, result.get(0)); + assertEquals(baseFile, result.get(1)); + } + + @Test + @DisplayName("findMediaFilesByPlaylistId returns empty list for non-existent playlist") + void testFindMediaFilesByPlaylistIdEmpty() { + List result = playlistMediaFileRepository.findMediaFilesByPlaylistId(-1); + assertEquals(0, result.size()); + } +} diff --git a/airsonic-main/src/test/java/org/airsonic/player/service/PlaylistServiceTest.java b/airsonic-main/src/test/java/org/airsonic/player/service/PlaylistServiceTest.java index 2ea5980e8..2f7e9f406 100644 --- a/airsonic-main/src/test/java/org/airsonic/player/service/PlaylistServiceTest.java +++ b/airsonic-main/src/test/java/org/airsonic/player/service/PlaylistServiceTest.java @@ -17,8 +17,8 @@ import java.util.*; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -39,6 +39,9 @@ public class PlaylistServiceTest { @Mock private AsyncWebSocketClient asyncWebSocketClient; + @Mock + private PlaylistMediaFileRepository playlistMediaFileRepository; + @Mock private PlaylistCache playlistCache; @@ -72,7 +75,7 @@ public void testGetAllPlaylists() { List result = playlistService.getAllPlaylists(); - assertThat(result).isEqualTo(playlists); + assertEquals(playlists, result); verify(playlistRepository).findAll(any(Sort.class)); } @@ -85,7 +88,7 @@ public void testGetReadablePlaylistsForUser() { List result = playlistService.getReadablePlaylistsForUser("testuser"); - assertThat(result).hasSize(1); + assertEquals(1, result.size()); verify(playlistRepository).findByUsername(anyString()); verify(playlistRepository).findBySharedTrue(); verify(playlistRepository).findByUsernameNotAndSharedUsersUsername(anyString(), anyString()); @@ -98,7 +101,7 @@ public void testGetWritablePlaylistsForUser() { List result = playlistService.getWritablePlaylistsForUser("testuser"); - assertThat(result).hasSize(1); + assertEquals(1, result.size()); verify(userRepository).findByUsername(anyString()); verify(playlistRepository).findByUsernameOrderByNameAsc(anyString()); } @@ -110,7 +113,7 @@ public void testGetPlaylist() { Playlist result = playlistService.getPlaylist(1); - assertThat(result).isEqualTo(playlist); + assertEquals(playlist, result); verify(playlistCache).getPlaylistById(anyInt()); verify(playlistRepository).findById(anyInt()); verify(playlistCache).putPlaylistById(anyInt(), any(Playlist.class)); @@ -125,7 +128,7 @@ public void testGetPlaylistUsers() { List result = playlistService.getPlaylistUsers(1); - assertThat(result).contains("testuser"); + assertTrue(result.contains("testuser")); verify(playlistCache).getUsersForPlaylist(anyInt()); verify(playlistRepository).findById(anyInt()); verify(playlistCache).putUsersForPlaylist(anyInt(), anyList()); @@ -134,26 +137,25 @@ public void testGetPlaylistUsers() { @Test public void testGetFilesInPlaylist() { // Create 10 media files, half of them are present in the playlist - List playlistMediaFiles = new ArrayList<>(); + List playlistMediaFiles = new ArrayList<>(); for (int i = 0; i < 10; i++) { MediaFile mediaFile = new MediaFile(); mediaFile.setId(i); mediaFile.setPresent(i % 2 == 0); - playlistMediaFiles.add(new PlaylistMediaFile(playlist, mediaFile, i)); + playlistMediaFiles.add(mediaFile); } - playlist.setPlaylistMediaFiles(playlistMediaFiles); - when(playlistRepository.findById(anyInt())).thenReturn(Optional.of(playlist)); + when(playlistMediaFileRepository.findMediaFilesByPlaylistId(anyInt())).thenReturn(playlistMediaFiles); // Get files in the playlist List result = playlistService.getFilesInPlaylist(1); // Assert that only the present files are returned - assertThat(result).hasSize(5); + assertEquals(5, result.size()); for (int i = 0; i < 5; i++) { - assertThat(result.get(i).getId()).isEqualTo(i * 2); + assertEquals(i * 2, result.get(i).getId()); } // Verify that the playlist was fetched and the files were filtered - verify(playlistRepository).findById(anyInt()); + verifyNoInteractions(playlistRepository); } @Test @@ -171,14 +173,14 @@ public void testSetFilesInPlaylist() { Playlist result = playlistService.setFilesInPlaylist(1, files); - assertThat(result).isEqualTo(playlist); + assertEquals(playlist, result); verify(playlistRepository).findById(anyInt()); verify(playlistRepository).saveAndFlush(any(Playlist.class)); - assertThat(result.getDuration()).isEqualTo(1000.0 * 10); - assertThat(result.getFileCount()).isEqualTo(5); + assertEquals(1000.0 * 10, result.getDuration()); + assertEquals(5, result.getFileCount()); for (int i = 0; i < 5; i++) { - assertThat(result.getPlaylistMediaFiles().get(i).getOrderIndex()).isEqualTo(i); - assertThat(result.getPlaylistMediaFiles().get(i).getMediaFile().getId()).isEqualTo(i); + assertEquals(i, result.getPlaylistMediaFiles().get(i).getOrderIndex()); + assertEquals(i, result.getPlaylistMediaFiles().get(i).getMediaFile().getId()); } } @@ -205,7 +207,7 @@ public void testRefreshPlaylistsStats() { List result = playlistService.refreshPlaylistsStats(); - assertThat(result).hasSize(1); + assertEquals(1, result.size()); verify(playlistRepository).findAll(); verify(playlistRepository).save(any(Playlist.class)); } @@ -309,7 +311,7 @@ public void testIsExist() { boolean result = playlistService.isExist(1); - assertThat(result).isTrue(); + assertTrue(result); verify(playlistRepository).existsById(anyInt()); } @@ -319,7 +321,7 @@ public void testIsWriteAllowed() { boolean result = playlistService.isWriteAllowed(1, "testuser"); - assertThat(result).isTrue(); + assertTrue(result); verify(playlistRepository).existsByIdAndUsername(anyInt(), anyString()); } diff --git a/pom.xml b/pom.xml index 5c99606b6..fb0260098 100644 --- a/pom.xml +++ b/pom.xml @@ -158,7 +158,7 @@ org.jsoup jsoup - 1.21.1 + 1.21.2 com.sun.activation @@ -168,7 +168,7 @@ org.checkerframework checker-qual - 3.49.5 + 3.50.0 com.google.j2objc @@ -213,7 +213,7 @@ io.dropwizard.metrics metrics-core - 4.2.33 + 4.2.35 org.eclipse.persistence