* fix: Apply active filters to chapter count display (Closes #1793) getChapterCount was always returning the total count regardless of the active filter. When filtering by unread/downloaded/bookmarked, the count shown in the novel header stayed the same as the total. Added an optional filter parameter to getChapterCount and pass the current settingsFilter from useNovel so the displayed count matches the filtered chapter list. * fix lint warning and add tests for filtered chapter count - Use settingsFilter instead of novelSettings.filter in useNovel to fix the react-hooks/exhaustive-deps warning - Add tests for getChapterCount with filter parameter - Update chapterFilterToSQL mock in test setup to actually apply filter conditions so filtered count tests work correctly
This commit is contained in:
@@ -395,10 +395,18 @@ export const getPageChapters = async (
|
||||
return query.all();
|
||||
};
|
||||
|
||||
export const getChapterCount = async (novelId: number, page: string = '1') =>
|
||||
export const getChapterCount = async (
|
||||
novelId: number,
|
||||
page: string = '1',
|
||||
filter?: ChapterFilterKey[],
|
||||
) =>
|
||||
await dbManager.$count(
|
||||
chapterSchema,
|
||||
and(eq(chapterSchema.novelId, novelId), eq(chapterSchema.page, page)),
|
||||
and(
|
||||
eq(chapterSchema.novelId, novelId),
|
||||
eq(chapterSchema.page, page),
|
||||
chapterFilterToSQL(filter),
|
||||
),
|
||||
);
|
||||
|
||||
export const getPageChaptersBatched = async (
|
||||
|
||||
@@ -712,6 +712,54 @@ describe('ChapterQueries', () => {
|
||||
|
||||
expect(result).toBe(2);
|
||||
});
|
||||
|
||||
it('should return filtered count when filter is provided', async () => {
|
||||
const testDb = getTestDb();
|
||||
const novelId = await insertTestNovel(testDb, { inLibrary: true });
|
||||
await insertTestChapter(testDb, novelId, {
|
||||
page: '1',
|
||||
unread: true,
|
||||
});
|
||||
await insertTestChapter(testDb, novelId, {
|
||||
page: '1',
|
||||
unread: false,
|
||||
});
|
||||
await insertTestChapter(testDb, novelId, {
|
||||
page: '1',
|
||||
unread: true,
|
||||
});
|
||||
|
||||
const total = await getChapterCount(novelId, '1');
|
||||
expect(total).toBe(3);
|
||||
|
||||
const unreadOnly = await getChapterCount(novelId, '1', ['not-read']);
|
||||
expect(unreadOnly).toBe(2);
|
||||
|
||||
const readOnly = await getChapterCount(novelId, '1', ['read']);
|
||||
expect(readOnly).toBe(1);
|
||||
});
|
||||
|
||||
it('should return total count when no filter is provided', async () => {
|
||||
const testDb = getTestDb();
|
||||
const novelId = await insertTestNovel(testDb, { inLibrary: true });
|
||||
await insertTestChapter(testDb, novelId, {
|
||||
page: '1',
|
||||
unread: true,
|
||||
});
|
||||
await insertTestChapter(testDb, novelId, {
|
||||
page: '1',
|
||||
unread: false,
|
||||
});
|
||||
|
||||
const result = await getChapterCount(novelId, '1');
|
||||
expect(result).toBe(2);
|
||||
|
||||
const noFilter = await getChapterCount(novelId, '1', undefined);
|
||||
expect(noFilter).toBe(2);
|
||||
|
||||
const emptyFilter = await getChapterCount(novelId, '1', []);
|
||||
expect(emptyFilter).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPageChaptersBatched', () => {
|
||||
|
||||
@@ -115,10 +115,26 @@ jest.mock('expo-document-picker', () => ({
|
||||
}));
|
||||
|
||||
// Mock database utilities
|
||||
jest.mock('@database/utils/parser', () => ({
|
||||
chapterFilterToSQL: jest.fn().mockReturnValue(undefined),
|
||||
chapterOrderToSQL: jest.fn().mockReturnValue(undefined),
|
||||
}));
|
||||
jest.mock('@database/utils/parser', () => {
|
||||
const { sql } = require('drizzle-orm');
|
||||
return {
|
||||
chapterFilterToSQL: jest.fn().mockImplementation(filter => {
|
||||
if (!filter || !filter.length) return undefined;
|
||||
const map: Record<string, string> = {
|
||||
'read': '`unread`=0',
|
||||
'not-read': '`unread`=1',
|
||||
'downloaded': 'isDownloaded=1',
|
||||
'not-downloaded': 'isDownloaded=0',
|
||||
'bookmarked': 'bookmark=1',
|
||||
'not-bookmarked': 'bookmark=0',
|
||||
};
|
||||
const parts = filter.map((f: string) => map[f]).filter(Boolean);
|
||||
if (!parts.length) return undefined;
|
||||
return sql.raw(parts.join(' AND '));
|
||||
}),
|
||||
chapterOrderToSQL: jest.fn().mockReturnValue(undefined),
|
||||
};
|
||||
});
|
||||
|
||||
// Mock database constants
|
||||
jest.mock('@database/constants', () => ({
|
||||
|
||||
@@ -238,7 +238,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
|
||||
|
||||
const config = [novel.id, settingsSort, settingsFilter, page] as const;
|
||||
|
||||
let chapterCount = await getChapterCount(novel.id, page);
|
||||
let chapterCount = await getChapterCount(novel.id, page, settingsFilter);
|
||||
|
||||
if (chapterCount) {
|
||||
try {
|
||||
@@ -259,7 +259,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
|
||||
});
|
||||
await insertChapters(novel.id, sourceChapters);
|
||||
newChapters = await _getPageChapters(...config);
|
||||
chapterCount = await getChapterCount(novel.id, page);
|
||||
chapterCount = await getChapterCount(novel.id, page, settingsFilter);
|
||||
}
|
||||
|
||||
setBatchInformation({
|
||||
@@ -271,7 +271,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
|
||||
|
||||
const unread = await _getFirstUnreadChapter(
|
||||
novel.id,
|
||||
novelSettings.filter,
|
||||
settingsFilter,
|
||||
page,
|
||||
);
|
||||
setFirstUnreadChapter(unread ?? undefined);
|
||||
|
||||
Reference in New Issue
Block a user