fix(tests): properly mock $fetch in useApi tests

Replace vi.mocked($fetch) with a properly stubbed global mock
using vi.stubGlobal() to fix test failures
This commit is contained in:
2026-02-04 15:22:09 +01:00
parent 37972aa660
commit 07917a500b

View File

@@ -16,13 +16,8 @@ vi.mock('#app', () => ({
})); }));
// Mock $fetch globally // Mock $fetch globally
vi.mock('#app', () => ({ const mockFetch = vi.fn();
useRuntimeConfig: vi.fn(() => ({ vi.stubGlobal('$fetch', mockFetch);
public: {
apiBase: 'http://localhost:3100/api'
}
}))
}))
describe('useApi', () => { describe('useApi', () => {
beforeEach(() => { beforeEach(() => {
@@ -36,7 +31,7 @@ describe('useApi', () => {
describe('GET requests', () => { describe('GET requests', () => {
it('should make a GET request and populate data on success', async () => { it('should make a GET request and populate data on success', async () => {
const mockData = { id: 1, name: 'Test' }; const mockData = { id: 1, name: 'Test' };
vi.mocked($fetch).mockResolvedValueOnce(mockData); mockFetch.mockResolvedValueOnce(mockData);
const api = useApi(); const api = useApi();
const result = api.get<typeof mockData>('/test'); const result = api.get<typeof mockData>('/test');
@@ -48,7 +43,7 @@ describe('useApi', () => {
// Wait for the async operation // Wait for the async operation
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData));
expect($fetch).toHaveBeenCalledWith('/test', { expect(mockFetch).toHaveBeenCalledWith('/test', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'GET', method: 'GET',
body: undefined, body: undefined,
@@ -60,14 +55,14 @@ describe('useApi', () => {
it('should handle GET request with custom options', async () => { it('should handle GET request with custom options', async () => {
const mockData = { result: 'success' }; const mockData = { result: 'success' };
vi.mocked($fetch).mockResolvedValueOnce(mockData); mockFetch.mockResolvedValueOnce(mockData);
const api = useApi(); const api = useApi();
const result = api.get('/test', { headers: { 'X-Custom': 'header' } }); const result = api.get('/test', { headers: { 'X-Custom': 'header' } });
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData));
expect($fetch).toHaveBeenCalledWith('/test', { expect(mockFetch).toHaveBeenCalledWith('/test', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'GET', method: 'GET',
headers: { 'X-Custom': 'header' }, headers: { 'X-Custom': 'header' },
@@ -79,23 +74,23 @@ describe('useApi', () => {
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);
expect($fetch).not.toHaveBeenCalled(); expect(mockFetch).not.toHaveBeenCalled();
expect(result.data.value).toBeNull(); expect(result.data.value).toBeNull();
expect(result.loading.value).toBe(false); expect(result.loading.value).toBe(false);
}); });
it('should execute when run() is called manually', async () => { it('should execute when run() is called manually', async () => {
const mockData = { manual: true }; const mockData = { manual: true };
vi.mocked($fetch).mockResolvedValueOnce(mockData); mockFetch.mockResolvedValueOnce(mockData);
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);
expect($fetch).not.toHaveBeenCalled(); expect(mockFetch).not.toHaveBeenCalled();
await result.run(); await result.run();
expect($fetch).toHaveBeenCalledWith('/test', { expect(mockFetch).toHaveBeenCalledWith('/test', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'GET', method: 'GET',
body: undefined, body: undefined,
@@ -107,14 +102,14 @@ describe('useApi', () => {
describe('DELETE requests', () => { describe('DELETE requests', () => {
it('should make a DELETE request', async () => { it('should make a DELETE request', async () => {
const mockData = { deleted: true }; const mockData = { deleted: true };
vi.mocked($fetch).mockResolvedValueOnce(mockData); mockFetch.mockResolvedValueOnce(mockData);
const api = useApi(); const api = useApi();
const result = api.del<typeof mockData>('/test/1'); const result = api.del<typeof mockData>('/test/1');
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData));
expect($fetch).toHaveBeenCalledWith('/test/1', { expect(mockFetch).toHaveBeenCalledWith('/test/1', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'DELETE', method: 'DELETE',
body: undefined, body: undefined,
@@ -127,7 +122,7 @@ describe('useApi', () => {
it('should make a POST request with body', async () => { it('should make a POST request with body', async () => {
const mockResponse = { id: 1, created: true }; const mockResponse = { id: 1, created: true };
const requestBody = { name: 'New Item' }; const requestBody = { name: 'New Item' };
vi.mocked($fetch).mockResolvedValueOnce(mockResponse); mockFetch.mockResolvedValueOnce(mockResponse);
const api = useApi(); const api = useApi();
const result = api.post<typeof mockResponse, typeof requestBody>( const result = api.post<typeof mockResponse, typeof requestBody>(
@@ -139,7 +134,7 @@ describe('useApi', () => {
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse));
expect($fetch).toHaveBeenCalledWith('/test', { expect(mockFetch).toHaveBeenCalledWith('/test', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'POST', method: 'POST',
body: requestBody, body: requestBody,
@@ -149,7 +144,7 @@ describe('useApi', () => {
it('should allow run() to be called with a different body', async () => { it('should allow run() to be called with a different body', async () => {
const mockResponse = { success: true }; const mockResponse = { success: true };
vi.mocked($fetch).mockResolvedValueOnce(mockResponse); mockFetch.mockResolvedValueOnce(mockResponse);
const api = useApi(); const api = useApi();
const result = api.post<typeof mockResponse, { data: string }>('/test', {}, false); const result = api.post<typeof mockResponse, { data: string }>('/test', {}, false);
@@ -157,7 +152,7 @@ describe('useApi', () => {
const body = { data: 'runtime-data' }; const body = { data: 'runtime-data' };
await result.run(body); await result.run(body);
expect($fetch).toHaveBeenCalledWith('/test', { expect(mockFetch).toHaveBeenCalledWith('/test', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'POST', method: 'POST',
body, body,
@@ -170,7 +165,7 @@ describe('useApi', () => {
it('should make a PUT request with body', async () => { it('should make a PUT request with body', async () => {
const mockResponse = { updated: true }; const mockResponse = { updated: true };
const requestBody = { name: 'Updated Item' }; const requestBody = { name: 'Updated Item' };
vi.mocked($fetch).mockResolvedValueOnce(mockResponse); mockFetch.mockResolvedValueOnce(mockResponse);
const api = useApi(); const api = useApi();
const result = api.put<typeof mockResponse, typeof requestBody>( const result = api.put<typeof mockResponse, typeof requestBody>(
@@ -182,7 +177,7 @@ describe('useApi', () => {
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse));
expect($fetch).toHaveBeenCalledWith('/test/1', { expect(mockFetch).toHaveBeenCalledWith('/test/1', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'PUT', method: 'PUT',
body: requestBody, body: requestBody,
@@ -194,7 +189,7 @@ describe('useApi', () => {
it('should make a PATCH request with body', async () => { it('should make a PATCH request with body', async () => {
const mockResponse = { patched: true }; const mockResponse = { patched: true };
const requestBody = { field: 'value' }; const requestBody = { field: 'value' };
vi.mocked($fetch).mockResolvedValueOnce(mockResponse); mockFetch.mockResolvedValueOnce(mockResponse);
const api = useApi(); const api = useApi();
const result = api.patch<typeof mockResponse, typeof requestBody>( const result = api.patch<typeof mockResponse, typeof requestBody>(
@@ -206,7 +201,7 @@ describe('useApi', () => {
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockResponse));
expect($fetch).toHaveBeenCalledWith('/test/1', { expect(mockFetch).toHaveBeenCalledWith('/test/1', {
baseURL: 'http://localhost:3100/api', baseURL: 'http://localhost:3100/api',
method: 'PATCH', method: 'PATCH',
body: requestBody, body: requestBody,
@@ -228,7 +223,7 @@ describe('useApi', () => {
} as any, } as any,
}; };
vi.mocked($fetch).mockRejectedValueOnce(fetchError); mockFetch.mockRejectedValueOnce(fetchError);
const api = useApi(); const api = useApi();
const result = api.get('/test'); const result = api.get('/test');
@@ -246,7 +241,7 @@ describe('useApi', () => {
response: undefined, response: undefined,
}; };
vi.mocked($fetch).mockRejectedValueOnce(fetchError); mockFetch.mockRejectedValueOnce(fetchError);
const api = useApi(); const api = useApi();
const result = api.get('/test'); const result = api.get('/test');
@@ -264,7 +259,7 @@ describe('useApi', () => {
message: '', message: '',
}; };
vi.mocked($fetch).mockRejectedValueOnce(fetchError); mockFetch.mockRejectedValueOnce(fetchError);
const api = useApi(); const api = useApi();
const result = api.get('/test'); const result = api.get('/test');
@@ -284,7 +279,7 @@ describe('useApi', () => {
const mockData = { success: true }; const mockData = { success: true };
// First request fails // First request fails
vi.mocked($fetch).mockRejectedValueOnce(fetchError); mockFetch.mockRejectedValueOnce(fetchError);
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);
@@ -294,7 +289,7 @@ describe('useApi', () => {
expect(result.error.value?.message).toBe('First Error'); expect(result.error.value?.message).toBe('First Error');
// Second request succeeds // Second request succeeds
vi.mocked($fetch).mockResolvedValueOnce(mockData); mockFetch.mockResolvedValueOnce(mockData);
await result.run(); await result.run();
await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData)); await vi.waitFor(() => expect(result.data.value).toStrictEqual(mockData));
@@ -309,7 +304,7 @@ describe('useApi', () => {
resolvePromise = resolve; resolvePromise = resolve;
}); });
vi.mocked($fetch).mockReturnValueOnce(promise as any); mockFetch.mockReturnValueOnce(promise as any);
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);
@@ -335,7 +330,7 @@ describe('useApi', () => {
rejectPromise = reject; rejectPromise = reject;
}); });
vi.mocked($fetch).mockReturnValueOnce(promise as any); mockFetch.mockReturnValueOnce(promise as any);
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);
@@ -354,7 +349,7 @@ describe('useApi', () => {
describe('Return type structure', () => { describe('Return type structure', () => {
it('should return QueryResult with correct structure', async () => { it('should return QueryResult with correct structure', async () => {
vi.mocked($fetch).mockResolvedValueOnce({ test: 'data' }); mockFetch.mockResolvedValueOnce({ test: 'data' });
const api = useApi(); const api = useApi();
const result = api.get('/test', {}, false); const result = api.get('/test', {}, false);