semantic-ds-toolkit
Version:
Performance-first semantic layer for modern data stacks - Stable Column Anchors & intelligent inference
63 lines • 2.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const fx_cache_1 = require("../../src/operators/fx-cache");
describe('Operators: FXCache with Redis-like client', () => {
const realFetch = global.fetch;
beforeEach(() => {
global.fetch = jest.fn(async (_url) => ({
ok: true,
status: 200,
json: async () => ({ rates: { EUR: 0.91, USD: 1 } })
}));
});
afterEach(() => {
global.fetch = realFetch;
});
it('writes entries to Redis (setEx) with TTL and reads back after clearCache', async () => {
const store = new Map();
const redisStub = {
get: jest.fn(async (key) => store.get(key) ?? null),
setEx: jest.fn(async (key, _ttl, value) => {
store.set(key, value);
return 'OK';
}),
expire: jest.fn(async () => 'OK')
};
const fx = new fx_cache_1.FXCache(1000, { enableRedis: true, redisClient: redisStub, dataSources: ['ecb'] });
// First fetch should go to network and write to Redis
const first = await fx.getExchangeRate('USD', 'EUR', { mode: fx_cache_1.OfflineMode.NETWORK_FIRST });
expect(['ecb', 'fed', 'fallback']).toContain(first.source);
expect(redisStub.setEx).toHaveBeenCalled();
// ttlSeconds should be floor(ttlMs/1000) = 1
for (const call of redisStub.setEx.mock.calls) {
expect(call[1]).toBe(1);
}
// Clear in-memory cache and ensure we can read from Redis
fx.clearCache();
const second = await fx.getExchangeRate('USD', 'EUR', { mode: fx_cache_1.OfflineMode.CACHE_FIRST });
expect(second.source).toBe('cache');
expect(second.stale).toBe(false);
expect(redisStub.get).toHaveBeenCalled();
});
it('uses set+expire path when setEx is unavailable', async () => {
const store = new Map();
const redisStub = {
get: jest.fn(async (key) => store.get(key) ?? null),
set: jest.fn(async (key, value) => { store.set(key, value); return 'OK'; }),
expire: jest.fn(async (_key, _ttl) => 'OK')
};
const fx = new fx_cache_1.FXCache(2500, { enableRedis: true, redisClient: redisStub, dataSources: ['ecb'] });
const first = await fx.getExchangeRate('USD', 'EUR');
expect(['ecb', 'fed', 'fallback']).toContain(first.source);
expect(redisStub.set).toHaveBeenCalledTimes(2);
expect(redisStub.expire).toHaveBeenCalledTimes(2);
// ttlSeconds should be floor(2500/1000) = 2
for (const call of redisStub.expire.mock.calls) {
expect(call[1]).toBe(2);
}
fx.clearCache();
const second = await fx.getExchangeRate('USD', 'EUR', { mode: fx_cache_1.OfflineMode.CACHE_FIRST });
expect(second.source).toBe('cache');
});
});
//# sourceMappingURL=fx-cache-redis.test.js.map