mirror of
https://github.com/adityachandelgit/BookLore.git
synced 2026-01-08 01:59:47 -06:00
fix(bookdrop): fix 'Select All' query logic and improve filename fallback for missing metadata (#1828)
* fix(bookdrop): fix 'Select All' query logic and improve filename fallback for missing metadata Signed-off-by: Balázs Szücs <bszucs1209@gmail.com> * fix(tests): update BookDropServiceTest and PathPatternResolverTest to use findAllIds method Signed-off-by: Balázs Szücs <bszucs1209@gmail.com> --------- Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
@@ -31,5 +31,8 @@ public interface BookdropFileRepository extends JpaRepository<BookdropFileEntity
|
||||
|
||||
@Query("SELECT f.id FROM BookdropFileEntity f WHERE f.id NOT IN :excludedIds")
|
||||
List<Long> findAllExcludingIdsFlat(@Param("excludedIds") List<Long> excludedIds);
|
||||
|
||||
@Query("SELECT f.id FROM BookdropFileEntity f")
|
||||
List<Long> findAllIds();
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,12 @@ public class BookDropService {
|
||||
AtomicInteger failedCount,
|
||||
AtomicInteger totalFilesProcessed) {
|
||||
List<Long> excludedIds = Optional.ofNullable(request.getExcludedIds()).orElse(List.of());
|
||||
List<Long> allIds = bookdropFileRepository.findAllExcludingIdsFlat(excludedIds);
|
||||
List<Long> allIds;
|
||||
if (excludedIds.isEmpty()) {
|
||||
allIds = bookdropFileRepository.findAllIds();
|
||||
} else {
|
||||
allIds = bookdropFileRepository.findAllExcludingIdsFlat(excludedIds);
|
||||
}
|
||||
log.info("SelectAll: Total files to finalize (after exclusions): {}, Excluded IDs: {}", allIds.size(), excludedIds);
|
||||
|
||||
processFileChunks(allIds, metadataById, defaultLibraryId, defaultPathId, results, failedCount, totalFilesProcessed);
|
||||
|
||||
@@ -55,9 +55,19 @@ public class PathPatternResolver {
|
||||
return filename;
|
||||
}
|
||||
|
||||
String filenameBase = "Untitled";
|
||||
if (filename != null && !filename.isBlank()) {
|
||||
int lastDot = filename.lastIndexOf('.');
|
||||
if (lastDot > 0) {
|
||||
filenameBase = filename.substring(0, lastDot);
|
||||
} else {
|
||||
filenameBase = filename;
|
||||
}
|
||||
}
|
||||
|
||||
String title = sanitize(metadata != null && metadata.getTitle() != null
|
||||
? metadata.getTitle()
|
||||
: "Untitled");
|
||||
: filenameBase);
|
||||
|
||||
String subtitle = sanitize(metadata != null ? metadata.getSubtitle() : "");
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ class PathPatternResolverTest {
|
||||
@Test void allPlaceholdersMissing_yieldsJustExtension() {
|
||||
var book = createBook(null, null, null, null, null, null, null, null, null, "file.cbz");
|
||||
String pattern = "{title}-{authors}-{series}-{year}-{language}-{publisher}-{isbn}";
|
||||
assertThat(PathPatternResolver.resolvePattern(book, pattern)).isEqualTo("Untitled------.cbz");
|
||||
assertThat(PathPatternResolver.resolvePattern(book, pattern)).isEqualTo("file------.cbz");
|
||||
}
|
||||
|
||||
@Test void patternWithBackslashes_isSanitized() {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.adityachandel.booklore.service.bookdrop;
|
||||
|
||||
import com.adityachandel.booklore.config.AppProperties;
|
||||
import com.adityachandel.booklore.model.dto.request.BookdropFinalizeRequest;
|
||||
import com.adityachandel.booklore.model.dto.response.BookdropFinalizeResult;
|
||||
import com.adityachandel.booklore.repository.BookdropFileRepository;
|
||||
import com.adityachandel.booklore.repository.LibraryRepository;
|
||||
import com.adityachandel.booklore.service.NotificationService;
|
||||
import com.adityachandel.booklore.service.file.FileMovingHelper;
|
||||
import com.adityachandel.booklore.service.monitoring.MonitoringRegistrationService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class BookDropServiceFinalizeTest {
|
||||
|
||||
@Mock
|
||||
private BookdropFileRepository bookdropFileRepository;
|
||||
@Mock
|
||||
private BookdropMonitoringService bookdropMonitoringService;
|
||||
@Mock
|
||||
private LibraryRepository libraryRepository;
|
||||
@Mock
|
||||
private MonitoringRegistrationService monitoringRegistrationService;
|
||||
@Mock
|
||||
private NotificationService notificationService;
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
@Mock
|
||||
private FileMovingHelper fileMovingHelper;
|
||||
@Mock
|
||||
private AppProperties appProperties;
|
||||
@Mock
|
||||
private BookdropNotificationService bookdropNotificationService;
|
||||
|
||||
@InjectMocks
|
||||
private BookDropService bookDropService;
|
||||
|
||||
@Test
|
||||
void finalizeImport_selectAll_emptyExcludedIds_shouldCallFindAllIds() {
|
||||
BookdropFinalizeRequest request = new BookdropFinalizeRequest();
|
||||
request.setSelectAll(true);
|
||||
request.setExcludedIds(Collections.emptyList());
|
||||
request.setDefaultLibraryId(1L);
|
||||
request.setDefaultPathId(1L);
|
||||
|
||||
when(bookdropFileRepository.findAllIds()).thenReturn(List.of(1L, 2L));
|
||||
when(bookdropFileRepository.findAllById(anyList())).thenReturn(Collections.emptyList()); // Mock chunk processing
|
||||
|
||||
bookDropService.finalizeImport(request);
|
||||
|
||||
verify(bookdropFileRepository).findAllIds();
|
||||
verify(bookdropFileRepository, never()).findAllExcludingIdsFlat(anyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
void finalizeImport_selectAll_withExcludedIds_shouldCallFindAllExcludingIdsFlat() {
|
||||
BookdropFinalizeRequest request = new BookdropFinalizeRequest();
|
||||
request.setSelectAll(true);
|
||||
request.setExcludedIds(List.of(3L));
|
||||
request.setDefaultLibraryId(1L);
|
||||
request.setDefaultPathId(1L);
|
||||
|
||||
when(bookdropFileRepository.findAllExcludingIdsFlat(anyList())).thenReturn(List.of(1L, 2L));
|
||||
when(bookdropFileRepository.findAllById(anyList())).thenReturn(Collections.emptyList()); // Mock chunk processing
|
||||
|
||||
bookDropService.finalizeImport(request);
|
||||
|
||||
verify(bookdropFileRepository).findAllExcludingIdsFlat(List.of(3L));
|
||||
verify(bookdropFileRepository, never()).findAllIds();
|
||||
}
|
||||
}
|
||||
@@ -286,7 +286,7 @@ class BookDropServiceTest {
|
||||
request.setDefaultLibraryId(999L);
|
||||
request.setDefaultPathId(1L);
|
||||
|
||||
when(bookdropFileRepository.findAllExcludingIdsFlat(any())).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllIds()).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllById(any())).thenReturn(List.of(bookdropFileEntity));
|
||||
when(libraryRepository.findById(999L)).thenReturn(Optional.empty());
|
||||
|
||||
@@ -387,7 +387,7 @@ class BookDropServiceTest {
|
||||
missingFileEntity.setOriginalMetadata("{\"title\":\"Missing Book\"}");
|
||||
missingFileEntity.setFetchedMetadata(null);
|
||||
|
||||
when(bookdropFileRepository.findAllExcludingIdsFlat(any())).thenReturn(List.of(2L));
|
||||
when(bookdropFileRepository.findAllIds()).thenReturn(List.of(2L));
|
||||
when(bookdropFileRepository.findAllById(any())).thenReturn(List.of(missingFileEntity));
|
||||
when(libraryRepository.findById(1L)).thenReturn(Optional.of(libraryEntity));
|
||||
|
||||
@@ -419,7 +419,7 @@ class BookDropServiceTest {
|
||||
request.setDefaultLibraryId(1L);
|
||||
request.setDefaultPathId(1L);
|
||||
|
||||
when(bookdropFileRepository.findAllExcludingIdsFlat(any())).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllIds()).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllById(any())).thenReturn(List.of(bookdropFileEntity));
|
||||
when(libraryRepository.findById(1L)).thenReturn(Optional.of(libraryEntity));
|
||||
|
||||
@@ -451,7 +451,7 @@ class BookDropServiceTest {
|
||||
request.setDefaultPathId(1L);
|
||||
request.setExcludedIds(List.of());
|
||||
|
||||
when(bookdropFileRepository.findAllExcludingIdsFlat(any())).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllIds()).thenReturn(List.of(1L));
|
||||
when(bookdropFileRepository.findAllById(any())).thenReturn(List.of(bookdropFileEntity));
|
||||
when(libraryRepository.findById(1L)).thenReturn(Optional.of(libraryEntity));
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ class PathPatternResolverTest {
|
||||
void testResolvePattern_nullMetadata() {
|
||||
String result = PathPatternResolver.resolvePattern((BookMetadata) null, "{title}", "original.pdf");
|
||||
|
||||
assertEquals("Untitled.pdf", result);
|
||||
assertEquals("original.pdf", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -195,7 +195,7 @@ class PathPatternResolverTest {
|
||||
|
||||
String result = PathPatternResolver.resolvePattern(metadata, "{title}", "original.pdf");
|
||||
|
||||
assertEquals("Untitled.pdf", result);
|
||||
assertEquals("original.pdf", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user