69 lines
3.0 KiB
TypeScript
69 lines
3.0 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { loadConfig } from '../src/config.js';
|
|
|
|
describe('loadConfig', () => {
|
|
it('applies defaults from an empty environment', () => {
|
|
const config = loadConfig({});
|
|
|
|
expect(config.host).toBe('0.0.0.0');
|
|
expect(config.port).toBe(8080);
|
|
expect(config.bearerToken).toBeUndefined();
|
|
expect(config.arena.baseUrl).toBe('https://api.arenasolutions.com/v1');
|
|
expect(config.arena.sessionTtlMs).toBe(24 * 60_000); // Arena TTL ~25 min; refresh 1 min early
|
|
expect(config.arena.httpTimeoutMs).toBe(30_000);
|
|
expect(config.pollIntervalMs).toBe(300_000);
|
|
expect(config.syncObjectOrder).toEqual(['PRODUCT', 'CHANGE_MASTER', 'BOM', 'DOCUMENTS']);
|
|
expect(config.webhookQueueMaxSize).toBe(10_000);
|
|
expect(config.shutdownTimeoutMs).toBe(30_000);
|
|
});
|
|
|
|
it('parses a custom sync order case-insensitively (ARN-001 config knob)', () => {
|
|
const config = loadConfig({ SYNC_OBJECT_ORDER: 'bom, product' });
|
|
expect(config.syncObjectOrder).toEqual(['BOM', 'PRODUCT']);
|
|
});
|
|
|
|
it('rejects unknown sync order entries', () => {
|
|
expect(() => loadConfig({ SYNC_OBJECT_ORDER: 'PRODUCT,WIDGET' })).toThrow(/WIDGET/);
|
|
});
|
|
|
|
it('rejects duplicate sync order entries (same rule as the HTTP contract uniqueItems)', () => {
|
|
expect(() => loadConfig({ SYNC_OBJECT_ORDER: 'BOM,BOM' })).toThrow(/duplicate entry "BOM"/);
|
|
expect(() => loadConfig({ SYNC_OBJECT_ORDER: 'product, bom, Product' })).toThrow(/duplicate entry "PRODUCT"/);
|
|
});
|
|
|
|
it('strips trailing slashes from the Arena base URL and parses numbers', () => {
|
|
const config = loadConfig({
|
|
ARENA_API_URL: 'https://api.arenasolutions.com/v1//',
|
|
ARENA_WORKSPACE_ID: '4242',
|
|
ARENA_SESSION_TTL_MINUTES: '10',
|
|
ARENA_HTTP_TIMEOUT_MS: '5000',
|
|
WORKER_PORT: '9090',
|
|
WEBHOOK_QUEUE_MAX_SIZE: '25',
|
|
SHUTDOWN_TIMEOUT_MS: '1500',
|
|
});
|
|
|
|
expect(config.arena.baseUrl).toBe('https://api.arenasolutions.com/v1');
|
|
expect(config.arena.workspaceId).toBe(4242);
|
|
expect(config.arena.sessionTtlMs).toBe(600_000);
|
|
expect(config.arena.httpTimeoutMs).toBe(5000);
|
|
expect(config.port).toBe(9090);
|
|
expect(config.webhookQueueMaxSize).toBe(25);
|
|
expect(config.shutdownTimeoutMs).toBe(1500);
|
|
});
|
|
|
|
it('rejects non-numeric numeric env values', () => {
|
|
expect(() => loadConfig({ WORKER_PORT: 'abc' })).toThrow(/WORKER_PORT/);
|
|
});
|
|
|
|
it('rejects numeric env values with trailing garbage (whole string must be digits)', () => {
|
|
expect(() => loadConfig({ WORKER_PORT: '8080abc' })).toThrow(/WORKER_PORT.*"8080abc"/);
|
|
expect(() => loadConfig({ ARENA_SESSION_TTL_MINUTES: '24m' })).toThrow(/ARENA_SESSION_TTL_MINUTES/);
|
|
expect(() => loadConfig({ WEBHOOK_QUEUE_MAX_SIZE: '1e4' })).toThrow(/WEBHOOK_QUEUE_MAX_SIZE/);
|
|
});
|
|
|
|
it('rejects zero and negative numeric env values', () => {
|
|
expect(() => loadConfig({ WEBHOOK_QUEUE_MAX_SIZE: '0' })).toThrow(/WEBHOOK_QUEUE_MAX_SIZE/);
|
|
expect(() => loadConfig({ SHUTDOWN_TIMEOUT_MS: '-1' })).toThrow(/SHUTDOWN_TIMEOUT_MS/);
|
|
});
|
|
});
|