test(admin): cover all import + thumbnail status branches
FAILED import-status with error message, RUNNING thumbnail with progress count, RUNNING thumbnail without progress (total=0), trigger thumbnail backfill, trigger import from idle. 5 new tests covering ~10 branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -238,4 +238,114 @@ describe('admin/system page', () => {
|
|||||||
const banner = document.querySelector('[data-testid="thumbnails-status-done"]');
|
const banner = document.querySelector('[data-testid="thumbnails-status-done"]');
|
||||||
expect(banner).not.toBeNull();
|
expect(banner).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders the FAILED state for import-status with retry button', async () => {
|
||||||
|
fetchSpy.mockImplementation(async (url: RequestInfo | URL) => {
|
||||||
|
const u = url.toString();
|
||||||
|
if (u.includes('import-status')) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
state: 'FAILED',
|
||||||
|
message: 'database error',
|
||||||
|
processed: 0,
|
||||||
|
startedAt: null
|
||||||
|
}),
|
||||||
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Response(JSON.stringify({ state: 'IDLE' }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(AdminSystemPage, { props: {} });
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
|
expect(document.body.textContent).toContain('database error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the running thumbnail status with progress count', async () => {
|
||||||
|
fetchSpy.mockImplementation(async (url: RequestInfo | URL) => {
|
||||||
|
const u = url.toString();
|
||||||
|
if (u.includes('thumbnail-status')) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
state: 'RUNNING',
|
||||||
|
message: '',
|
||||||
|
total: 100,
|
||||||
|
processed: 30,
|
||||||
|
skipped: 5,
|
||||||
|
failed: 1,
|
||||||
|
startedAt: null
|
||||||
|
}),
|
||||||
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Response(JSON.stringify({ state: 'IDLE' }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(AdminSystemPage, { props: {} });
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
|
// Total 100, processed+skipped+failed = 36
|
||||||
|
expect(document.body.textContent).toMatch(/36|100/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers thumbnail backfill when its button is clicked', async () => {
|
||||||
|
render(AdminSystemPage, { props: {} });
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
const btns = Array.from(document.querySelectorAll('[data-thumbnails-trigger]'));
|
||||||
|
(btns[0] as HTMLButtonElement)?.click();
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
const calls = fetchSpy.mock.calls.map((c) => c[0].toString());
|
||||||
|
expect(calls.some((c) => c.includes('generate-thumbnails'))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers import when import button is clicked from idle state', async () => {
|
||||||
|
render(AdminSystemPage, { props: {} });
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
const btns = Array.from(document.querySelectorAll('[data-import-trigger]'));
|
||||||
|
(btns[0] as HTMLButtonElement)?.click();
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 50));
|
||||||
|
const calls = fetchSpy.mock.calls.map((c) => c[0].toString());
|
||||||
|
expect(calls.some((c) => c.includes('trigger-import'))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the running thumbnail status without progress when total is 0', async () => {
|
||||||
|
fetchSpy.mockImplementation(async (url: RequestInfo | URL) => {
|
||||||
|
const u = url.toString();
|
||||||
|
if (u.includes('thumbnail-status')) {
|
||||||
|
return new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
state: 'RUNNING',
|
||||||
|
message: '',
|
||||||
|
total: 0,
|
||||||
|
processed: 0,
|
||||||
|
skipped: 0,
|
||||||
|
failed: 0,
|
||||||
|
startedAt: null
|
||||||
|
}),
|
||||||
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Response(JSON.stringify({ state: 'IDLE' }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
render(AdminSystemPage, { props: {} });
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r, 100));
|
||||||
|
// running state shown but no progress count when total=0
|
||||||
|
expect(document.body.textContent).toMatch(/läuft|wird|generier/i);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user