mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
Merge branch 'main' into ebook-piecewise
This commit is contained in:
@@ -44,7 +44,7 @@ describe('Admin requests routes', () => {
|
||||
jobQueueMock.addNotificationJob.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it('returns recent requests', async () => {
|
||||
it('returns recent requests (legacy endpoint)', async () => {
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([
|
||||
{
|
||||
id: 'req-1',
|
||||
@@ -66,6 +66,172 @@ describe('Admin requests routes', () => {
|
||||
expect(payload.requests[0].torrentUrl).toBe('http://torrent');
|
||||
});
|
||||
|
||||
it('returns paginated requests with default params', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(1);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([
|
||||
{
|
||||
id: 'req-1',
|
||||
status: 'pending',
|
||||
createdAt: new Date(),
|
||||
completedAt: null,
|
||||
errorMessage: null,
|
||||
audiobook: { id: 'ab-1', title: 'Title', author: 'Author' },
|
||||
user: { id: 'u-1', plexUsername: 'user' },
|
||||
downloadHistory: [{ torrentUrl: 'http://torrent' }],
|
||||
},
|
||||
]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
const response = await GET(mockRequest as any);
|
||||
const payload = await response.json();
|
||||
|
||||
expect(payload.requests).toHaveLength(1);
|
||||
expect(payload.total).toBe(1);
|
||||
expect(payload.page).toBe(1);
|
||||
expect(payload.pageSize).toBe(25);
|
||||
expect(payload.totalPages).toBe(1);
|
||||
expect(payload.requests[0].userId).toBe('u-1');
|
||||
});
|
||||
|
||||
it('filters requests by status', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(1);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([
|
||||
{
|
||||
id: 'req-1',
|
||||
status: 'failed',
|
||||
createdAt: new Date(),
|
||||
completedAt: null,
|
||||
errorMessage: 'Search failed',
|
||||
audiobook: { id: 'ab-1', title: 'Title', author: 'Author' },
|
||||
user: { id: 'u-1', plexUsername: 'user' },
|
||||
downloadHistory: [],
|
||||
},
|
||||
]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests?status=failed',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
const response = await GET(mockRequest as any);
|
||||
const payload = await response.json();
|
||||
|
||||
expect(payload.requests).toHaveLength(1);
|
||||
expect(payload.requests[0].status).toBe('failed');
|
||||
expect(prismaMock.request.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: expect.objectContaining({
|
||||
status: 'failed',
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('filters requests by userId', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(1);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([
|
||||
{
|
||||
id: 'req-1',
|
||||
status: 'pending',
|
||||
createdAt: new Date(),
|
||||
completedAt: null,
|
||||
errorMessage: null,
|
||||
audiobook: { id: 'ab-1', title: 'Title', author: 'Author' },
|
||||
user: { id: 'user-123', plexUsername: 'specificuser' },
|
||||
downloadHistory: [],
|
||||
},
|
||||
]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests?userId=user-123',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
const response = await GET(mockRequest as any);
|
||||
const payload = await response.json();
|
||||
|
||||
expect(payload.requests).toHaveLength(1);
|
||||
expect(prismaMock.request.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: expect.objectContaining({
|
||||
userId: 'user-123',
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('searches requests by title/author', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(1);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([
|
||||
{
|
||||
id: 'req-1',
|
||||
status: 'pending',
|
||||
createdAt: new Date(),
|
||||
completedAt: null,
|
||||
errorMessage: null,
|
||||
audiobook: { id: 'ab-1', title: 'Harry Potter', author: 'J.K. Rowling' },
|
||||
user: { id: 'u-1', plexUsername: 'user' },
|
||||
downloadHistory: [],
|
||||
},
|
||||
]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests?search=Harry',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
const response = await GET(mockRequest as any);
|
||||
const payload = await response.json();
|
||||
|
||||
expect(payload.requests).toHaveLength(1);
|
||||
expect(payload.requests[0].title).toBe('Harry Potter');
|
||||
});
|
||||
|
||||
it('paginates requests correctly', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(100);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests?page=3&pageSize=10',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
const response = await GET(mockRequest as any);
|
||||
const payload = await response.json();
|
||||
|
||||
expect(payload.page).toBe(3);
|
||||
expect(payload.pageSize).toBe(10);
|
||||
expect(payload.totalPages).toBe(10);
|
||||
expect(prismaMock.request.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
skip: 20, // (page - 1) * pageSize = 2 * 10
|
||||
take: 10,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('sorts requests by different fields', async () => {
|
||||
prismaMock.request.count.mockResolvedValueOnce(1);
|
||||
prismaMock.request.findMany.mockResolvedValueOnce([]);
|
||||
|
||||
const mockRequest = {
|
||||
url: 'http://localhost/api/admin/requests?sortBy=title&sortOrder=asc',
|
||||
};
|
||||
|
||||
const { GET } = await import('@/app/api/admin/requests/route');
|
||||
await GET(mockRequest as any);
|
||||
|
||||
expect(prismaMock.request.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
orderBy: { audiobook: { title: 'asc' } },
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('soft deletes a request via delete service', async () => {
|
||||
deleteRequestMock.mockResolvedValueOnce({
|
||||
success: true,
|
||||
|
||||
@@ -29,6 +29,11 @@ const pathMapperMock = vi.hoisted(() => ({
|
||||
}));
|
||||
const invalidateQbMock = vi.hoisted(() => vi.fn());
|
||||
const invalidateSabMock = vi.hoisted(() => vi.fn());
|
||||
const invalidateDownloadClientManagerMock = vi.hoisted(() => vi.fn());
|
||||
const downloadClientManagerMock = vi.hoisted(() => ({
|
||||
getAllClients: vi.fn(),
|
||||
testConnection: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/db', () => ({
|
||||
prisma: prismaMock,
|
||||
@@ -67,12 +72,20 @@ vi.mock('@/lib/integrations/sabnzbd.service', () => ({
|
||||
invalidateSABnzbdService: invalidateSabMock,
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/services/download-client-manager.service', () => ({
|
||||
getDownloadClientManager: () => downloadClientManagerMock,
|
||||
invalidateDownloadClientManager: invalidateDownloadClientManagerMock,
|
||||
}));
|
||||
|
||||
describe('Admin settings core routes', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
authRequest = { user: { id: 'admin-1', role: 'admin' }, json: vi.fn() };
|
||||
requireAuthMock.mockImplementation((_req: any, handler: any) => handler(authRequest));
|
||||
requireAdminMock.mockImplementation((_req: any, handler: any) => handler());
|
||||
// Reset download client manager mocks with default values
|
||||
downloadClientManagerMock.getAllClients.mockResolvedValue([]);
|
||||
downloadClientManagerMock.testConnection.mockResolvedValue({ success: true, message: 'Connected' });
|
||||
});
|
||||
|
||||
it('returns settings payload', async () => {
|
||||
|
||||
Reference in New Issue
Block a user