Unify Harbor error handling across server and client
This commit is contained in:
61
test/web/api-errors.test.js
Normal file
61
test/web/api-errors.test.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import {
|
||||
HarborApiError,
|
||||
request,
|
||||
validationStatusForError,
|
||||
} 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);
|
||||
});
|
||||
|
||||
test('subscription validation distinguishes bad input from provider outage', () => {
|
||||
assert.equal(validationStatusForError({ code: 'SUBSCRIPTION_INVALID' }), 'invalid');
|
||||
assert.equal(validationStatusForError({ code: 'PROVIDER_UNAVAILABLE' }), 'unavailable');
|
||||
});
|
||||
Reference in New Issue
Block a user