Files
harbor-net/test/web/api-errors.test.js
T
dokril 005c7a101b
Build and Deploy Gateway / build-and-push (push) Successful in 15s
Build and Deploy Gateway / deploy (push) Successful in 13s
Refine subscription import and refresh flow
2026-07-12 11:18:33 +03:00

56 lines
1.7 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
HarborApiError,
request,
} from '../../src/web/api.js';
const response = (status, error) => ({
ok: status >= 200 && status < 300,
status,
json: async () => ({ success: false, error }),
});
test('frontend exposes retry only for retryable structured errors', async () => {
await assert.rejects(
request('/api/test', {}, async () => response(502, {
code: 'PROVIDER_UNAVAILABLE',
message: 'untrusted server copy',
retryable: false,
correlationId: 'provider-reference',
})),
(error) => {
assert.ok(error instanceof HarborApiError);
assert.equal(error.message, 'Провайдер подписки временно недоступен.');
assert.equal(error.retryable, true);
assert.equal(error.correlationId, 'provider-reference');
return true;
},
);
await assert.rejects(
request('/api/test', {}, async () => response(400, {
code: 'SUBSCRIPTION_INVALID',
retryable: true,
})),
(error) => error.retryable === false,
);
});
test('network failures become retryable control errors', async () => {
await assert.rejects(
request('/api/state', {}, async () => { throw new TypeError('fetch failed'); }),
(error) => error.code === 'CONTROL_UNREACHABLE' && error.retryable === true,
);
});
test('local unknown errors get a safe message and diagnostic reference', () => {
const error = new HarborApiError({ code: 'NOT_A_REAL_CODE' });
assert.equal(error.code, 'UNKNOWN');
assert.equal(error.message, 'Не удалось выполнить действие.');
assert.equal(typeof error.correlationId, 'string');
assert.ok(error.correlationId.length >= 8);
});