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