Files
esg/test/unit/timeout-deadline-bugs.spec.ts
s.hajizadeh 61098f1bf4 feat: add car inquiries with resilience, ownership privacy, and retry visibility
Introduce plate, chassis, and third-party car endpoints, a wall-clock inquiry
deadline with transport-only retries, and ownership-safe no-match errors so
another person's identity never leaks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-05 17:21:16 +03:30

50 lines
1.7 KiB
TypeScript

import {
INQUIRY_DEADLINE_MS,
createAttemptTrail,
runWithProviderResilience,
toAttemptErrorFields,
} from '../../src/common/helpers/provider-resilience.helper';
import { ProviderExecutionContext } from '../../src/common/interfaces/inquiry-provider.interface';
describe('timeout / deadline resilience bugs', () => {
it('maps withTimeout ETIMEDOUT errors to PROVIDER_TIMEOUT (not PROVIDER_ERROR)', () => {
const error = new Error('PARSIAN request timed out after 20000ms');
(error as NodeJS.ErrnoException).code = 'ETIMEDOUT';
expect(toAttemptErrorFields(error)).toMatchObject({
code: 'PROVIDER_TIMEOUT',
messageFa: expect.stringMatching(/زمان/),
});
});
it('caps attempt timeout by inquiry deadline even when provider timeout is higher', async () => {
const context: ProviderExecutionContext = {
requestId: 'req',
trackingCode: 'trk',
deadlineAt: Date.now() + 80,
attemptTrail: createAttemptTrail(),
};
const started = Date.now();
await expect(
runWithProviderResilience(
() => new Promise((resolve) => setTimeout(() => resolve('late'), 500)),
{
providerName: 'PARSIAN',
maxAttempts: 1,
timeoutMs: 30_000,
context,
label: 'PARSIAN request',
},
),
).rejects.toMatchObject({ code: 'ETIMEDOUT' });
expect(Date.now() - started).toBeLessThan(250);
});
it('default inquiry deadline must exceed a single slow CentInsur SOAP (~30s)', () => {
// thirdPartyCar may need two SOAP calls over a proxy; 20s was killing successful ~28s responses
expect(INQUIRY_DEADLINE_MS).toBeGreaterThanOrEqual(60_000);
});
});