118 lines
2.9 KiB
TypeScript
118 lines
2.9 KiB
TypeScript
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { CandlesService } from './candles.service';
|
|
import { MoexClientService } from '../moex-client/moex-client.service';
|
|
import { CacheService } from '../cache/cache.service';
|
|
import { CandleInterval } from './dto/candles-query.dto';
|
|
|
|
describe('CandlesService', () => {
|
|
let service: CandlesService;
|
|
let moexClient: Pick<MoexClientService, 'getCandles'>;
|
|
let cache: Pick<CacheService, 'getOrFetch'>;
|
|
|
|
beforeEach(async () => {
|
|
moexClient = {
|
|
getCandles: vi.fn(),
|
|
};
|
|
cache = {
|
|
getOrFetch: vi.fn(async (_keyPrefix, _keyParts, fetchFn) => ({
|
|
data: await fetchFn(),
|
|
fromCache: false,
|
|
cachedAt: '2026-06-15T00:00:00.000Z',
|
|
})),
|
|
};
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
providers: [
|
|
CandlesService,
|
|
{ provide: MoexClientService, useValue: moexClient },
|
|
{ provide: CacheService, useValue: cache },
|
|
],
|
|
}).compile();
|
|
|
|
service = module.get<CandlesService>(CandlesService);
|
|
});
|
|
|
|
it('uses MOEX interval 24 for daily share candles and maps output envelope', async () => {
|
|
vi.mocked(moexClient.getCandles).mockResolvedValue([
|
|
{
|
|
open: 320,
|
|
high: 325,
|
|
low: 318,
|
|
close: 323,
|
|
volume: 1500000,
|
|
value: 480000000,
|
|
begin: '2026-05-01 00:00:00',
|
|
end: '2026-05-01 23:59:59',
|
|
},
|
|
]);
|
|
|
|
const result = await service.getCandles(
|
|
'shares',
|
|
'SBER',
|
|
CandleInterval.DAY,
|
|
'2026-05-01',
|
|
'2026-06-01',
|
|
);
|
|
|
|
expect(cache.getOrFetch).toHaveBeenCalledWith(
|
|
'candles',
|
|
['shares', 'SBER', '24', '2026-05-01', '2026-06-01'],
|
|
expect.any(Function),
|
|
'candlesTtl',
|
|
);
|
|
expect(moexClient.getCandles).toHaveBeenCalledWith(
|
|
'stock',
|
|
'shares',
|
|
'SBER',
|
|
24,
|
|
'2026-05-01',
|
|
'2026-06-01',
|
|
);
|
|
expect(result).toEqual({
|
|
data: [
|
|
{
|
|
open: 320,
|
|
high: 325,
|
|
low: 318,
|
|
close: 323,
|
|
volume: 1500000,
|
|
value: 480000000,
|
|
begin: '2026-05-01 00:00:00',
|
|
end: '2026-05-01 23:59:59',
|
|
},
|
|
],
|
|
meta: {
|
|
fromCache: false,
|
|
cachedAt: '2026-06-15T00:00:00.000Z',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('uses MOEX interval 60 for hourly bond candles without live MOEX dependency', async () => {
|
|
vi.mocked(moexClient.getCandles).mockResolvedValue([]);
|
|
|
|
await service.getCandles(
|
|
'bonds',
|
|
'SU26238RMFS5',
|
|
CandleInterval.HOUR,
|
|
'2026-05-01',
|
|
'2026-06-01',
|
|
);
|
|
|
|
expect(cache.getOrFetch).toHaveBeenCalledWith(
|
|
'candles',
|
|
['bonds', 'SU26238RMFS5', '60', '2026-05-01', '2026-06-01'],
|
|
expect.any(Function),
|
|
'candlesTtl',
|
|
);
|
|
expect(moexClient.getCandles).toHaveBeenCalledWith(
|
|
'stock',
|
|
'bonds',
|
|
'SU26238RMFS5',
|
|
60,
|
|
'2026-05-01',
|
|
'2026-06-01',
|
|
);
|
|
});
|
|
});
|