fix(quota): normalize DeepSeek timeout errors
This commit is contained in:
@@ -422,6 +422,12 @@ describe('NeuralWatt quota provider (VS Code parity)', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('DeepSeek quota provider (VS Code parity)', () => {
|
describe('DeepSeek quota provider (VS Code parity)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const fsMock = fs as unknown as { existsSync: () => boolean; readFileSync: () => string };
|
||||||
|
fsMock.existsSync = () => true;
|
||||||
|
fsMock.readFileSync = () => AUTH;
|
||||||
|
});
|
||||||
|
|
||||||
test('builds credits_balance window from documented USD payload (string balance)', async () => {
|
test('builds credits_balance window from documented USD payload (string balance)', async () => {
|
||||||
stubFetchReturning(() => Promise.resolve(mockResponse({
|
stubFetchReturning(() => Promise.resolve(mockResponse({
|
||||||
is_available: true,
|
is_available: true,
|
||||||
@@ -463,6 +469,15 @@ describe('DeepSeek quota provider (VS Code parity)', () => {
|
|||||||
assert.equal(result.error, 'Session expired — please re-authenticate with DeepSeek');
|
assert.equal(result.error, 'Session expired — please re-authenticate with DeepSeek');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('reports a normalized timeout error', async () => {
|
||||||
|
stubFetchReturning(() => Promise.reject(new DOMException('The operation timed out.', 'TimeoutError')));
|
||||||
|
|
||||||
|
const result = await fetchQuotaForProvider('deepseek');
|
||||||
|
|
||||||
|
assert.equal(result.ok, false);
|
||||||
|
assert.equal(result.error, 'Request timed out');
|
||||||
|
});
|
||||||
|
|
||||||
test('returns no-quota-data on a 200 payload with no usable balance', async () => {
|
test('returns no-quota-data on a 200 payload with no usable balance', async () => {
|
||||||
stubFetchReturning(() => Promise.resolve(mockResponse({
|
stubFetchReturning(() => Promise.resolve(mockResponse({
|
||||||
is_available: true,
|
is_available: true,
|
||||||
@@ -488,4 +503,10 @@ describe('DeepSeek quota provider (VS Code parity)', () => {
|
|||||||
assert.equal(result.ok, true);
|
assert.equal(result.ok, true);
|
||||||
assert.equal(result.usage!.windows.credits_balance!.valueLabel, '$0.00');
|
assert.equal(result.usage!.windows.credits_balance!.valueLabel, '$0.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('teardown: restore fs', () => {
|
||||||
|
const fsMock = fs as unknown as { existsSync: unknown; readFileSync: unknown };
|
||||||
|
fsMock.existsSync = ORIGINAL_FS.existsSync;
|
||||||
|
fsMock.readFileSync = ORIGINAL_FS.readFileSync;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2285,7 +2285,9 @@ const fetchDeepseekQuota = async (): Promise<ProviderResult> => {
|
|||||||
usage: { windows },
|
usage: { windows },
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const isTimeout = error instanceof DOMException && error.name === 'AbortError' && timeoutSignal.aborted;
|
const isTimeout = error instanceof DOMException && (
|
||||||
|
error.name === 'TimeoutError' || (error.name === 'AbortError' && timeoutSignal.aborted)
|
||||||
|
);
|
||||||
const isParseError = error instanceof SyntaxError;
|
const isParseError = error instanceof SyntaxError;
|
||||||
return buildResult({
|
return buildResult({
|
||||||
providerId: 'deepseek',
|
providerId: 'deepseek',
|
||||||
|
|||||||
@@ -99,7 +99,9 @@ export const fetchQuota = async () => {
|
|||||||
usage: { windows }
|
usage: { windows }
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const isTimeout = error instanceof DOMException && error.name === 'AbortError' && timeoutSignal.aborted;
|
const isTimeout = error instanceof DOMException && (
|
||||||
|
error.name === 'TimeoutError' || (error.name === 'AbortError' && timeoutSignal.aborted)
|
||||||
|
);
|
||||||
const isParseError = error instanceof SyntaxError;
|
const isParseError = error instanceof SyntaxError;
|
||||||
return buildResult({
|
return buildResult({
|
||||||
providerId,
|
providerId,
|
||||||
|
|||||||
@@ -119,6 +119,15 @@ describe('DeepSeek quota provider', () => {
|
|||||||
expect(result.error).toBe('Invalid response from provider');
|
expect(result.error).toBe('Invalid response from provider');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reports a normalized timeout error', async () => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new DOMException('The operation timed out.', 'TimeoutError')));
|
||||||
|
|
||||||
|
const result = await fetchQuota();
|
||||||
|
|
||||||
|
expect(result.ok).toBe(false);
|
||||||
|
expect(result.error).toBe('Request timed out');
|
||||||
|
});
|
||||||
|
|
||||||
it('returns no-quota-data on a 200 payload with no usable balance', async () => {
|
it('returns no-quota-data on a 200 payload with no usable balance', async () => {
|
||||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(mockResponse({
|
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(mockResponse({
|
||||||
is_available: true,
|
is_available: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user