mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(metadata): omit unknown page counts from file writes
Normalize stored zero values at the shared write payload boundary so every format omits an unknown page count. Align collection repository tests with the query shape left after podcast removal. Closes #2040
This commit is contained in:
@@ -104,8 +104,7 @@ describe('CollectionRepository', () => {
|
|||||||
const orderBy = vi.fn().mockResolvedValue([{ id: 1, memberCount: 2 }]);
|
const orderBy = vi.fn().mockResolvedValue([{ id: 1, memberCount: 2 }]);
|
||||||
const groupBy = vi.fn().mockReturnValue({ orderBy });
|
const groupBy = vi.fn().mockReturnValue({ orderBy });
|
||||||
const where = vi.fn().mockReturnValue({ groupBy });
|
const where = vi.fn().mockReturnValue({ groupBy });
|
||||||
const thirdLeftJoin = vi.fn().mockReturnValue({ where });
|
const secondLeftJoin = vi.fn().mockReturnValue({ where });
|
||||||
const secondLeftJoin = vi.fn().mockReturnValue({ leftJoin: thirdLeftJoin });
|
|
||||||
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
||||||
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
||||||
db.select.mockReturnValueOnce({ from } as never);
|
db.select.mockReturnValueOnce({ from } as never);
|
||||||
@@ -116,15 +115,13 @@ describe('CollectionRepository', () => {
|
|||||||
expect(rows).toEqual([{ id: 1, memberCount: 2 }]);
|
expect(rows).toEqual([{ id: 1, memberCount: 2 }]);
|
||||||
expect(db.select).toHaveBeenCalledWith(expect.objectContaining({ memberCount: expect.anything() }));
|
expect(db.select).toHaveBeenCalledWith(expect.objectContaining({ memberCount: expect.anything() }));
|
||||||
expect(secondLeftJoin).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ op: 'and' }));
|
expect(secondLeftJoin).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ op: 'and' }));
|
||||||
expect(thirdLeftJoin).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ op: 'eq' }));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('findAllVisibleForUser keeps public metadata visible while counting only viewer-visible books', async () => {
|
it('findAllVisibleForUser keeps public metadata visible while counting only viewer-visible books', async () => {
|
||||||
const orderBy = vi.fn().mockResolvedValue([{ id: 1, bookCount: 1 }]);
|
const orderBy = vi.fn().mockResolvedValue([{ id: 1, bookCount: 1 }]);
|
||||||
const groupBy = vi.fn().mockReturnValue({ orderBy });
|
const groupBy = vi.fn().mockReturnValue({ orderBy });
|
||||||
const where = vi.fn().mockReturnValue({ groupBy });
|
const where = vi.fn().mockReturnValue({ groupBy });
|
||||||
const thirdLeftJoin = vi.fn().mockReturnValue({ where });
|
const secondLeftJoin = vi.fn().mockReturnValue({ where });
|
||||||
const secondLeftJoin = vi.fn().mockReturnValue({ leftJoin: thirdLeftJoin });
|
|
||||||
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
||||||
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
||||||
db.select.mockReturnValueOnce({ from } as never);
|
db.select.mockReturnValueOnce({ from } as never);
|
||||||
@@ -134,8 +131,8 @@ describe('CollectionRepository', () => {
|
|||||||
expect(rows).toEqual([{ id: 1, bookCount: 1 }]);
|
expect(rows).toEqual([{ id: 1, bookCount: 1 }]);
|
||||||
expect(where).toHaveBeenCalledWith(
|
expect(where).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
op: 'and',
|
op: 'or',
|
||||||
clauses: expect.arrayContaining([expect.objectContaining({ op: 'or' }), expect.objectContaining({ op: 'eq', right: 'books' })]),
|
clauses: expect.arrayContaining([expect.objectContaining({ op: 'eq', right: 5 }), expect.objectContaining({ op: 'eq', right: true })]),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
expect(secondLeftJoin).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ op: 'and' }));
|
expect(secondLeftJoin).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ op: 'and' }));
|
||||||
@@ -145,8 +142,7 @@ describe('CollectionRepository', () => {
|
|||||||
const limit = vi.fn().mockResolvedValue([{ id: 10, bookCount: 1 }]);
|
const limit = vi.fn().mockResolvedValue([{ id: 10, bookCount: 1 }]);
|
||||||
const groupBy = vi.fn().mockReturnValue({ limit });
|
const groupBy = vi.fn().mockReturnValue({ limit });
|
||||||
const where = vi.fn().mockReturnValue({ groupBy });
|
const where = vi.fn().mockReturnValue({ groupBy });
|
||||||
const thirdLeftJoin = vi.fn().mockReturnValue({ where });
|
const secondLeftJoin = vi.fn().mockReturnValue({ where });
|
||||||
const secondLeftJoin = vi.fn().mockReturnValue({ leftJoin: thirdLeftJoin });
|
|
||||||
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
const firstLeftJoin = vi.fn().mockReturnValue({ leftJoin: secondLeftJoin });
|
||||||
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
const from = vi.fn().mockReturnValue({ leftJoin: firstLeftJoin });
|
||||||
db.select.mockReturnValueOnce({ from } as never);
|
db.select.mockReturnValueOnce({ from } as never);
|
||||||
@@ -156,13 +152,7 @@ describe('CollectionRepository', () => {
|
|||||||
expect(where).toHaveBeenCalledWith(
|
expect(where).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
op: 'and',
|
op: 'and',
|
||||||
clauses: expect.arrayContaining([
|
clauses: expect.arrayContaining([expect.objectContaining({ op: 'eq', right: 10 }), expect.objectContaining({ op: 'or' })]),
|
||||||
expect.objectContaining({
|
|
||||||
op: 'and',
|
|
||||||
clauses: expect.arrayContaining([expect.objectContaining({ op: 'or' })]),
|
|
||||||
}),
|
|
||||||
expect.objectContaining({ op: 'eq', right: 'books' }),
|
|
||||||
]),
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -136,6 +136,18 @@ describe('FileWriteRepository', () => {
|
|||||||
await expect(repo.loadPayload(11)).resolves.toBeNull();
|
await expect(repo.loadPayload(11)).resolves.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loadPayload normalizes an unknown zero page count to null', async () => {
|
||||||
|
const metadataChain = chain([{ title: 'Unknown length', pageCount: 0 }]);
|
||||||
|
const emptyRelatedRows = chain([]);
|
||||||
|
const db = {
|
||||||
|
select: vi.fn().mockReturnValue(emptyRelatedRows).mockReturnValueOnce(metadataChain),
|
||||||
|
};
|
||||||
|
|
||||||
|
const repo = new FileWriteRepository(db as never);
|
||||||
|
|
||||||
|
await expect(repo.loadPayload(12)).resolves.toMatchObject({ pageCount: null });
|
||||||
|
});
|
||||||
|
|
||||||
it('loadPayload maps metadata, authors, genres, and tags', async () => {
|
it('loadPayload maps metadata, authors, genres, and tags', async () => {
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Dune',
|
title: 'Dune',
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ export class FileWriteRepository {
|
|||||||
publishedDate: meta.publishedDate,
|
publishedDate: meta.publishedDate,
|
||||||
publishedYear: meta.publishedYear,
|
publishedYear: meta.publishedYear,
|
||||||
language: meta.language,
|
language: meta.language,
|
||||||
pageCount: meta.pageCount,
|
pageCount: typeof meta.pageCount === 'number' && meta.pageCount > 0 ? meta.pageCount : null,
|
||||||
seriesName: meta.seriesName,
|
seriesName: meta.seriesName,
|
||||||
seriesIndex: meta.seriesIndex,
|
seriesIndex: meta.seriesIndex,
|
||||||
isbn10: meta.isbn10,
|
isbn10: meta.isbn10,
|
||||||
|
|||||||
Reference in New Issue
Block a user