test(import): use MSW route handlers
- replace direct fetch stubs with shared MSW handlers - keep fetch spying only for request assertions - cover the shell prefetch with an issues counts handler
This commit is contained in:
parent
7a0548ac94
commit
e65ec37c9e
1 changed files with 117 additions and 132 deletions
|
|
@ -3,6 +3,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { ShellBridge, ShellPageId } from '@/platform/shell/bridge';
|
||||
import { HttpResponse, http, server } from '@/test/msw';
|
||||
|
||||
import { createAppQueryClient } from '@/app/query-client';
|
||||
import { AppRouterProvider, createAppRouter } from '@/app/router';
|
||||
|
|
@ -10,13 +11,6 @@ import { AppRouterProvider, createAppRouter } from '@/app/router';
|
|||
import type { ImportStagingFile } from './-import.types';
|
||||
import { resetImportWorkflowStore } from './-import.store';
|
||||
|
||||
function createResponse(body: unknown, status = 200) {
|
||||
return new Response(JSON.stringify(body), {
|
||||
status,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
function createShellBridge(overrides: Partial<ShellBridge> = {}): ShellBridge {
|
||||
return {
|
||||
getCurrentProfileContext: vi.fn(() => ({ profileId: 2, isAdmin: true })),
|
||||
|
|
@ -83,22 +77,18 @@ describe('import route', () => {
|
|||
window.SoulSyncWebShellBridge = createShellBridge();
|
||||
window.showToast = vi.fn();
|
||||
window.showConfirmDialog = vi.fn(async () => true);
|
||||
vi.spyOn(globalThis, 'fetch');
|
||||
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn(async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const url = input instanceof Request ? input.url : String(input);
|
||||
|
||||
if (url.includes('/api/import/staging/files')) {
|
||||
return createResponse({
|
||||
server.use(
|
||||
http.get('/api/import/staging/files', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
staging_path: '/music/Staging',
|
||||
files: stagingFilesPayload,
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/import/staging/groups')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/import/staging/groups', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
groups: [
|
||||
{
|
||||
|
|
@ -109,10 +99,9 @@ describe('import route', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/import/staging/suggestions')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/import/staging/suggestions', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
ready: true,
|
||||
suggestions: [
|
||||
|
|
@ -126,10 +115,9 @@ describe('import route', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/import/search/albums')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/import/search/albums', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
albums: [
|
||||
{
|
||||
|
|
@ -142,18 +130,11 @@ describe('import route', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/import/album/match')) {
|
||||
const body =
|
||||
input instanceof Request
|
||||
? ((await input.clone().json()) as Record<string, unknown>)
|
||||
: (JSON.parse(typeof init?.body === 'string' ? init.body : '{}') as Record<
|
||||
string,
|
||||
unknown
|
||||
>);
|
||||
}),
|
||||
http.post('/api/import/album/match', async ({ request }) => {
|
||||
const body = (await request.json()) as Record<string, unknown>;
|
||||
albumMatchBodies.push(body);
|
||||
return createResponse({
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
received: body,
|
||||
album: {
|
||||
|
|
@ -175,27 +156,24 @@ describe('import route', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/auto-import/status')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/auto-import/status', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
running: true,
|
||||
current_status: 'idle',
|
||||
active_imports: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/auto-import/settings')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/auto-import/settings', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
scan_interval: 60,
|
||||
confidence_threshold: 0.9,
|
||||
});
|
||||
}
|
||||
|
||||
if (url.includes('/api/auto-import/results')) {
|
||||
return createResponse({
|
||||
}),
|
||||
http.get('/api/auto-import/results', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
results: [
|
||||
{
|
||||
|
|
@ -210,10 +188,19 @@ describe('import route', () => {
|
|||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return createResponse({ success: true });
|
||||
}) as unknown as typeof fetch,
|
||||
}),
|
||||
http.get('/api/issues/counts', () => {
|
||||
return HttpResponse.json({
|
||||
success: true,
|
||||
counts: {
|
||||
open: 0,
|
||||
in_progress: 0,
|
||||
resolved: 0,
|
||||
dismissed: 0,
|
||||
total: 0,
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -227,9 +214,7 @@ describe('import route', () => {
|
|||
await waitFor(() =>
|
||||
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/groups'))).toBe(true),
|
||||
);
|
||||
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/suggestions'))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/suggestions'))).toBe(true);
|
||||
expect(window.SoulSyncWebShellBridge?.showReactHost).toHaveBeenCalledWith('import');
|
||||
expect(window.SoulSyncWebShellBridge?.setActivePageChrome).toHaveBeenCalledWith('import');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue