56 lines
1.7 KiB
JavaScript
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);
|
||
});
|