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); });