-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: simplified fetch wrapper and enhance type safety
- Updated `NetrcMachine` and `SessionState` interfaces to use `RegionCode` for improved type safety. - Refactored login actions to handle optional chaining for better error handling. - Enhanced API calls to utilize the new `customFetch` utility with improved type definitions. - Added tests for `customFetch` to ensure robust error handling and response management.
- Loading branch information
1 parent
17f4c54
commit a770c11
Showing
13 changed files
with
238 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { describe, expect, it, vi } from 'vitest' | ||
import { customFetch, FetchError } from './fetch' | ||
|
||
// Mock fetch | ||
const mockFetch = vi.fn() | ||
globalThis.fetch = mockFetch | ||
|
||
describe('customFetch', () => { | ||
it('should make a successful GET request', async () => { | ||
const mockResponse = { data: 'test' } | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'application/json' }, | ||
json: () => Promise.resolve(mockResponse), | ||
}) | ||
|
||
const result = await customFetch('https://api.test.com') | ||
expect(result).toEqual(mockResponse) | ||
}) | ||
|
||
it('should handle object body by stringifying it', async () => { | ||
const body = { test: 'data' } | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'application/json' }, | ||
json: () => Promise.resolve({}), | ||
}) | ||
|
||
await customFetch('https://api.test.com', { body }) | ||
|
||
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com', expect.objectContaining({ | ||
body: JSON.stringify(body), | ||
})) | ||
}) | ||
|
||
it('should pass string body as-is without modification', async () => { | ||
const body = '{"test":"data"}' | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'application/json' }, | ||
json: () => Promise.resolve({}), | ||
}) | ||
|
||
await customFetch('https://api.test.com', { body }) | ||
|
||
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com', expect.objectContaining({ | ||
body, | ||
})) | ||
}) | ||
|
||
it('should handle array body by stringifying it', async () => { | ||
const body = ['test', 'data'] | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'application/json' }, | ||
json: () => Promise.resolve({}), | ||
}) | ||
|
||
await customFetch('https://api.test.com', { body }) | ||
|
||
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com', expect.objectContaining({ | ||
body: JSON.stringify(body), | ||
})) | ||
}) | ||
|
||
it('should handle non-JSON responses', async () => { | ||
const textResponse = 'Hello World' | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'text/plain' }, | ||
text: () => Promise.resolve(textResponse), | ||
}) | ||
|
||
await expect(customFetch('https://api.test.com')).rejects.toThrow(FetchError) | ||
}) | ||
|
||
it('should throw FetchError for HTTP errors', async () => { | ||
const errorResponse = { message: 'Not Found' } | ||
mockFetch.mockResolvedValue({ | ||
ok: false, | ||
status: 404, | ||
statusText: 'Not Found', | ||
json: () => Promise.resolve(errorResponse), | ||
}) | ||
|
||
await expect(customFetch('https://api.test.com')).rejects.toThrow(FetchError) | ||
await expect(customFetch('https://api.test.com')).rejects.toMatchObject({ | ||
response: { | ||
status: 404, | ||
statusText: 'Not Found', | ||
data: errorResponse, | ||
}, | ||
}) | ||
}) | ||
|
||
it('should handle network errors', async () => { | ||
mockFetch.mockRejectedValue(new Error('Network Error')) | ||
|
||
await expect(customFetch('https://api.test.com')).rejects.toThrow(FetchError) | ||
await expect(customFetch('https://api.test.com')).rejects.toMatchObject({ | ||
response: { | ||
status: 0, | ||
statusText: 'Network Error', | ||
data: null, | ||
}, | ||
}) | ||
}) | ||
|
||
it('should set correct headers', async () => { | ||
mockFetch.mockResolvedValueOnce({ | ||
ok: true, | ||
headers: { get: () => 'application/json' }, | ||
json: () => Promise.resolve({}), | ||
}) | ||
|
||
await customFetch('https://api.test.com', { | ||
headers: { | ||
Authorization: 'Bearer token', | ||
}, | ||
}) | ||
|
||
expect(mockFetch).toHaveBeenCalledWith('https://api.test.com', expect.objectContaining({ | ||
headers: expect.objectContaining({ | ||
'Content-Type': 'application/json', | ||
'Authorization': 'Bearer token', | ||
}), | ||
})) | ||
}) | ||
}) |
Oops, something went wrong.