fix(library): expose rename setting in scoped library list

Return fileRenameEnabled for non-superuser library responses so the bulk rename selector includes configured libraries.

Closes #918
This commit is contained in:
neon
2026-08-08 04:26:17 +00:00
parent ddf285f568
commit 27040d5dee
4 changed files with 163 additions and 1 deletions
@@ -6,6 +6,7 @@ vi.mock('drizzle-orm', () => ({
sql: vi.fn((strings: TemplateStringsArray, ...values: unknown[]) => ({ op: 'sql', text: strings.join(''), values })),
}));
import { libraries } from '../../db/schema';
import { LibraryRepository } from './library.repository';
describe('LibraryRepository', () => {
@@ -51,6 +52,24 @@ describe('LibraryRepository', () => {
expect(txUpdateSet).toHaveBeenNthCalledWith(2, { displayOrder: 6 });
});
it('findAllForUser includes file rename eligibility in the scoped library projection', async () => {
const orderBy = vi.fn().mockResolvedValue([]);
const groupBy = vi.fn().mockReturnValue({ orderBy });
const leftJoin = vi.fn().mockReturnValue({ groupBy });
const innerJoin = vi.fn().mockReturnValue({ leftJoin });
const from = vi.fn().mockReturnValue({ innerJoin });
db.select.mockReturnValue({ from });
await repo.findAllForUser(42);
expect(db.select).toHaveBeenCalledWith(
expect.objectContaining({
fileRenameEnabled: libraries.fileRenameEnabled,
}),
);
expect(orderBy).toHaveBeenCalledWith(libraries.displayOrder, libraries.name);
});
it('getStats aggregates counts, sizes, and format map', async () => {
const countChain = {
from: vi.fn().mockReturnValue({
@@ -39,6 +39,7 @@ export class LibraryRepository {
displayOrder: libraries.displayOrder,
coverAspectRatio: libraries.coverAspectRatio,
scanMode: libraries.scanMode,
fileRenameEnabled: libraries.fileRenameEnabled,
createdAt: libraries.createdAt,
updatedAt: libraries.updatedAt,
bookCount: sql<number>`count(${books.id})::int`,
@@ -95,7 +95,7 @@ describe('LibraryService', () => {
});
it('findAll uses scoped folder query for non-superusers', async () => {
libraryRepo.findAllForUser.mockResolvedValue([{ id: 10, name: 'A', coverAspectRatio: '1/1' }]);
libraryRepo.findAllForUser.mockResolvedValue([{ id: 10, name: 'A', coverAspectRatio: '1/1', fileRenameEnabled: true }]);
libraryRepo.findFoldersByLibraryIds.mockResolvedValue([{ id: 1, libraryId: 10, path: '/a', createdAt: new Date() }]);
const result = await service.findAll({ id: 7, isSuperuser: false, contentFilters: EMPTY_CONTENT_FILTER_RULES } as any);
@@ -105,6 +105,7 @@ describe('LibraryService', () => {
expect(libraryRepo.findAllFolders).not.toHaveBeenCalled();
expect(result[0].folders).toEqual([{ id: 1, path: '/a', createdAt: expect.any(Date) }]);
expect(result[0].coverAspectRatio).toBe('1/1');
expect(result[0].fileRenameEnabled).toBe(true);
});
it('passes contentFilters to findAllForUser for non-superuser and skips for superuser', async () => {