@noves/noves-sdk
Version:
Noves Developer Kit
132 lines (120 loc) • 4.95 kB
text/typescript
/**
* 1.5.0 Release Test — FetchConfig (NEW)
*
* Tests the new SDK-level FetchConfig:
* - Timeout: requests abort after timeout
* - AbortSignal: external cancellation
* - Custom headers: added to requests
* - Combined usage with retryConfig
*/
import { Translate, Pricing, FetchConfig } from '../dist/index';
import { section, pass, fail, runTest } from './helpers';
const API_KEY = process.env.NOVES_API_KEY!;
export async function testFetchConfig() {
section('NEW: FetchConfig (timeout, signal, headers)');
// 1. FetchConfig with timeout — should work with a generous timeout
await runTest('FetchConfig: timeout (generous, should succeed)', async () => {
const translate = Translate.evm({
apiKey: API_KEY,
fetchConfig: { timeout: 30000 } // 30s — plenty of time
});
const chains = await translate.getChains();
if (!chains || (Array.isArray(chains) && chains.length === 0)) {
throw new Error('Request with timeout=30s returned empty');
}
pass('FetchConfig: timeout (generous)', `Got chains successfully with timeout=30s`);
});
// 2. FetchConfig with very short timeout — should abort
await runTest('FetchConfig: timeout (1ms, should abort)', async () => {
const translate = Translate.evm({
apiKey: API_KEY,
fetchConfig: { timeout: 1 } // 1ms — will definitely time out
});
try {
await translate.getChains();
throw new Error('Expected timeout abort but request succeeded');
} catch (err: any) {
// Should be an AbortError or timeout-related error
if (err.name === 'AbortError' || err.message?.includes('abort') || err.message?.includes('timeout') || err.message?.includes('Timeout')) {
pass('FetchConfig: timeout (1ms)', `Correctly aborted: ${err.name || err.message}`);
} else {
// Any error is acceptable as long as it didn't succeed
pass('FetchConfig: timeout (1ms)', `Got error as expected: ${err.message?.substring(0, 80)}`);
}
}
});
// 3. FetchConfig with AbortSignal — abort before request completes
await runTest('FetchConfig: AbortSignal cancellation', async () => {
const controller = new AbortController();
const translate = Translate.evm({
apiKey: API_KEY,
fetchConfig: { signal: controller.signal }
});
// Abort immediately
setTimeout(() => controller.abort(), 1);
try {
await translate.getChains();
// If it succeeded very fast, that's okay too
pass('FetchConfig: AbortSignal', 'Request completed before abort (acceptable)');
} catch (err: any) {
if (err.name === 'AbortError' || err.message?.includes('abort')) {
pass('FetchConfig: AbortSignal', `Correctly aborted: ${err.name}`);
} else {
pass('FetchConfig: AbortSignal', `Got error (acceptable): ${err.message?.substring(0, 80)}`);
}
}
});
// 4. FetchConfig with custom headers — should not break anything
await runTest('FetchConfig: custom headers', async () => {
const translate = Translate.evm({
apiKey: API_KEY,
fetchConfig: {
headers: {
'X-Request-ID': 'release-test-1.5.0',
'X-Correlation-ID': 'noves-sdk-validation'
}
}
});
const chains = await translate.getChains();
if (!chains || (Array.isArray(chains) && chains.length === 0)) {
throw new Error('Request with custom headers returned empty');
}
pass('FetchConfig: custom headers', 'Request succeeded with custom headers');
});
// 5. FetchConfig with Pricing API
await runTest('FetchConfig: works with Pricing factory', async () => {
const pricing = Pricing.evm({
apiKey: API_KEY,
fetchConfig: { timeout: 30000 }
});
const chains = await pricing.getChains();
if (!chains) throw new Error('Pricing with fetchConfig returned null');
pass('FetchConfig: Pricing', 'Pricing.evm() works with fetchConfig');
});
// 6. Combined: fetchConfig + retryConfig
await runTest('FetchConfig: combined with retryConfig', async () => {
const translate = Translate.evm({
apiKey: API_KEY,
retryConfig: 'DEVELOPMENT',
fetchConfig: {
timeout: 30000,
headers: { 'X-Test': 'combined' }
}
});
const chains = await translate.getChains();
if (!chains) throw new Error('Combined config returned null');
pass('FetchConfig: combined', 'Works with both retryConfig + fetchConfig');
});
// 7. FetchConfig type is properly exported
await runTest('FetchConfig: type export check', async () => {
// This validates that FetchConfig is a usable type at compile-time
const config: FetchConfig = {
timeout: 5000,
headers: { 'X-Custom': 'value' }
};
if (!config.timeout || !config.headers) {
throw new Error('FetchConfig type not working');
}
pass('FetchConfig: type export', 'FetchConfig type is properly exported and usable');
});
}