Refs #5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QKHeGuAYh4W1jNdjMConZa
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { classify } from '../src/core/openai';
|
|
|
|
const res = (status: number, text = '') => ({ status, text });
|
|
|
|
describe('classify: 2xx', () => {
|
|
it('returns the text as is', () => {
|
|
expect(classify(res(200, '{"text":"привет"}'))).toEqual({ ok: true, text: 'привет' });
|
|
});
|
|
|
|
it('returns whitespace-only text unchanged (queue decides "no speech")', () => {
|
|
expect(classify(res(200, '{"text":" "}'))).toEqual({ ok: true, text: ' ' });
|
|
});
|
|
|
|
it.each(['<html>oops</html>', '{"foo":1}', '{"text":5}', 'null', '[]', '"str"'])(
|
|
'200 with %s → permanent',
|
|
(body) => {
|
|
expect(classify(res(200, body))).toEqual({
|
|
ok: false,
|
|
kind: 'permanent',
|
|
message: `HTTP 200: ответ без поля text: ${body}`,
|
|
});
|
|
},
|
|
);
|
|
|
|
it('cuts the body to 200 chars', () => {
|
|
const body = `<html>${'x'.repeat(1000)}`;
|
|
expect(classify(res(200, body))).toEqual({
|
|
ok: false,
|
|
kind: 'permanent',
|
|
message: `HTTP 200: ответ без поля text: ${body.slice(0, 200)}`,
|
|
});
|
|
});
|
|
|
|
it('empty 2xx body → permanent without snippet', () => {
|
|
expect(classify(res(204, ''))).toEqual({ ok: false, kind: 'permanent', message: 'HTTP 204: ответ без поля text' });
|
|
});
|
|
});
|
|
|
|
describe('classify: errors', () => {
|
|
it.each([301, 302, 399, 400, 401, 403, 404, 413, 415, 422, 499])('%i → permanent', (status) => {
|
|
expect(classify(res(status, 'x'))).toEqual({ ok: false, kind: 'permanent', message: `HTTP ${status}: x` });
|
|
});
|
|
|
|
it.each([100, 101, 408, 429, 500, 502, 503, 599, 600])('%i → temporary', (status) => {
|
|
expect(classify(res(status, 'x'))).toEqual({ ok: false, kind: 'temporary', message: `HTTP ${status}: x` });
|
|
});
|
|
|
|
it('takes error.message from an OpenAI-style body', () => {
|
|
expect(classify(res(401, '{"error":{"message":"Invalid API key"}}'))).toEqual({
|
|
ok: false,
|
|
kind: 'permanent',
|
|
message: 'HTTP 401: Invalid API key',
|
|
});
|
|
});
|
|
|
|
it.each(['{"error":{"message":""}}', '{"error":"bad"}', '{"error":null}'])(
|
|
'falls back to the body when error.message is unusable: %s',
|
|
(body) => {
|
|
expect(classify(res(400, body))).toEqual({ ok: false, kind: 'permanent', message: `HTTP 400: ${body}` });
|
|
},
|
|
);
|
|
|
|
it('cuts a plain body to 200 chars after trim', () => {
|
|
expect(classify(res(500, ` ${'y'.repeat(1000)}`))).toEqual({
|
|
ok: false,
|
|
kind: 'temporary',
|
|
message: `HTTP 500: ${'y'.repeat(200)}`,
|
|
});
|
|
});
|
|
|
|
it.each(['', ' \n '])('empty body %j → "HTTP <code>"', (body) => {
|
|
expect(classify(res(503, body))).toEqual({ ok: false, kind: 'temporary', message: 'HTTP 503' });
|
|
});
|
|
});
|