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