fix: исправить edge cases HttpClient
- ошибки парсинга успешных ответов проброшены в onError - добавлена защита от перезаписи явного Authorization - обновлены тесты, README и примеры кастомизации
This commit is contained in:
@@ -168,7 +168,9 @@ bun test -t "should generate client with custom name"
|
||||
- ✅ POST с body
|
||||
- ✅ Обработка 404 статуса
|
||||
- ✅ Bearer authentication через `onRequest`
|
||||
- ✅ Сохранение явно переданного `Authorization`
|
||||
- ✅ Retry через `onError` и `ApiError`
|
||||
- ✅ Ошибки парсинга успешного ответа в `onError`
|
||||
- ✅ Timeout через `AbortSignal`
|
||||
|
||||
|
||||
|
||||
@@ -382,6 +382,61 @@ describe('E2E Generation', () => {
|
||||
expect(profile.email).toBe('test@example.com');
|
||||
}, 60000);
|
||||
|
||||
test('onRequest не должен перетирать явно переданный Authorization', async () => {
|
||||
const outputPath = join(tempDir, 'output');
|
||||
|
||||
await execa('bun', [
|
||||
'run',
|
||||
CLI_PATH,
|
||||
'--input',
|
||||
FIXTURES.MINIMAL,
|
||||
'--output',
|
||||
outputPath,
|
||||
'--mode',
|
||||
'split',
|
||||
]);
|
||||
|
||||
const generatedFile = join(outputPath, 'index.ts');
|
||||
const { HttpClient } = await import(generatedFile);
|
||||
let authorizationHeader: string | null = null;
|
||||
|
||||
const http = new HttpClient({
|
||||
customFetch: async (_url, init) => {
|
||||
authorizationHeader = new Headers(init?.headers).get('Authorization');
|
||||
return Response.json({ ok: true });
|
||||
},
|
||||
onRequest: (params) => {
|
||||
if (!params.secure) {
|
||||
return params;
|
||||
}
|
||||
|
||||
const headers = new Headers(params.headers);
|
||||
|
||||
if (!headers.has('Authorization')) {
|
||||
headers.set('Authorization', 'Bearer default-token');
|
||||
}
|
||||
|
||||
return {
|
||||
...params,
|
||||
headers,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const result = await http.request({
|
||||
path: '/auth-header',
|
||||
method: 'GET',
|
||||
secure: true,
|
||||
format: 'json',
|
||||
headers: {
|
||||
Authorization: 'Bearer explicit-token',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({ ok: true });
|
||||
expect(authorizationHeader).toBe('Bearer explicit-token');
|
||||
}, 60000);
|
||||
|
||||
test('onError должен поддерживать retry после ApiError', async () => {
|
||||
const outputPath = join(tempDir, 'output');
|
||||
|
||||
@@ -429,6 +484,47 @@ describe('E2E Generation', () => {
|
||||
expect(result).toEqual({ ok: true });
|
||||
}, 60000);
|
||||
|
||||
test('onError должен получать ошибки парсинга успешного ответа', async () => {
|
||||
const outputPath = join(tempDir, 'output');
|
||||
|
||||
await execa('bun', [
|
||||
'run',
|
||||
CLI_PATH,
|
||||
'--input',
|
||||
FIXTURES.MINIMAL,
|
||||
'--output',
|
||||
outputPath,
|
||||
'--mode',
|
||||
'split',
|
||||
]);
|
||||
|
||||
const generatedFile = join(outputPath, 'index.ts');
|
||||
const { HttpClient } = await import(generatedFile);
|
||||
let handledError: unknown;
|
||||
|
||||
const http = new HttpClient({
|
||||
customFetch: async () => new Response('{ invalid json', {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}),
|
||||
onError: (error) => {
|
||||
handledError = error;
|
||||
return { parsed: false };
|
||||
},
|
||||
});
|
||||
|
||||
const result = await http.request({
|
||||
path: '/broken-json',
|
||||
method: 'GET',
|
||||
format: 'json',
|
||||
});
|
||||
|
||||
expect(result).toEqual({ parsed: false });
|
||||
expect(handledError).toBeInstanceOf(Error);
|
||||
}, 60000);
|
||||
|
||||
test('timeout должен отменять зависший запрос', async () => {
|
||||
const outputPath = join(tempDir, 'output');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user