- MoexHttpClient: infrastructure (axios, rate limiter, circuit breaker) - MoexSecuritiesClient: search and security descriptions - MoexMarketDataClient: share/bond market data and batch queries - MoexCandlesClient: candle data - MoexHistoryClient: share/bond history - MoexDividendsClient: dividend data - Removed @Global() from MoexClientModule - Updated all 7 consumers with explicit DI - All 141 tests passing
119 lines
5.4 KiB
TypeScript
119 lines
5.4 KiB
TypeScript
import 'reflect-metadata';
|
|
import { MoexHttpClient } from './moex-http.client';
|
|
import { MoexMarketDataClient } from './moex-market-data.client';
|
|
|
|
describe('MoexMarketDataClient', () => {
|
|
let client: MoexMarketDataClient;
|
|
let request: ReturnType<typeof vi.fn>;
|
|
let extractTable: ReturnType<typeof vi.fn>;
|
|
|
|
beforeEach(() => {
|
|
request = vi.fn();
|
|
extractTable = vi.fn();
|
|
client = new MoexMarketDataClient({ request, extractTable } as unknown as MoexHttpClient);
|
|
});
|
|
|
|
describe('getShareMarketData', () => {
|
|
it('возвращает рыночные данные акции из securities и marketdata таблиц', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable
|
|
.mockReturnValueOnce([{ SECID: 'SBER', BOARDID: 'TQBR', SHORTNAME: 'Сбербанк', PREVPRICE: '320' }])
|
|
.mockReturnValueOnce([{ SECID: 'SBER', BOARDID: 'TQBR', BID: '321', OFFER: '322', OPEN: '320', LOW: '319', HIGH: '323', LAST: '322.35', LASTCHANGE: '1.15', LASTCHANGEPRCNT: '0.36', VOLTODAY: '1925163', VALTODAY: '620184479', WAPRICE: '321.9', NUMTRADES: '12345', ISSUECAPITALIZATION: '6958336818320', TRADINGSTATUS: 'T', UPDATETIME: '10:30:00' }]);
|
|
|
|
const result = await client.getShareMarketData('SBER');
|
|
|
|
expect(request).toHaveBeenCalledWith('/engines/stock/markets/shares/securities/SBER', { boards: 'TQBR' });
|
|
expect(result).toMatchObject({ secid: 'SBER', boardid: 'TQBR', shortName: 'Сбербанк', last: 322.35, bid: 321, offer: 322 });
|
|
});
|
|
|
|
it('возвращает null если бумага не найдена', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable.mockReturnValueOnce([]).mockReturnValueOnce([]);
|
|
|
|
const result = await client.getShareMarketData('INVALID');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getShareMarketDataBatch', () => {
|
|
it('возвращает массив рыночных данных для нескольких бумаг', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable
|
|
.mockReturnValueOnce([
|
|
{ SECID: 'SBER', BOARDID: 'TQBR', SHORTNAME: 'Сбербанк', PREVPRICE: '320' },
|
|
{ SECID: 'VTBR', BOARDID: 'TQBR', SHORTNAME: 'ВТБ', PREVPRICE: '50' },
|
|
])
|
|
.mockReturnValueOnce([
|
|
{ SECID: 'SBER', BOARDID: 'TQBR', LAST: '322', BID: '321', OFFER: '323' },
|
|
{ SECID: 'VTBR', BOARDID: 'TQBR', LAST: '50.5', BID: '50.1', OFFER: '50.8' },
|
|
]);
|
|
|
|
const results = await client.getShareMarketDataBatch(['SBER', 'VTBR']);
|
|
|
|
expect(results).toHaveLength(2);
|
|
expect(results[0].secid).toBe('SBER');
|
|
expect(results[1].secid).toBe('VTBR');
|
|
});
|
|
});
|
|
|
|
describe('getBondData', () => {
|
|
it('возвращает данные облигации из securities таблицы', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable.mockReturnValueOnce([
|
|
{ SECID: 'SU26238RMFS4', BOARDID: 'TQCB', SHORTNAME: 'ОФЗ 26238', PREVWAPRICE: '98.5', COUPONVALUE: '34.5', NEXTCOUPON: '2025-01-15', MATDATE: '2041-05-15', FACEVALUE: '1000', ISIN: 'RU000A1038T7' },
|
|
]);
|
|
|
|
const result = await client.getBondData('SU26238RMFS4');
|
|
|
|
expect(request).toHaveBeenCalledWith('/engines/stock/markets/bonds/securities/SU26238RMFS4', { boards: 'TQCB' });
|
|
expect(result).toMatchObject({ secid: 'SU26238RMFS4', shortName: 'ОФЗ 26238' });
|
|
});
|
|
|
|
it('возвращает null если облигация не найдена', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable.mockReturnValueOnce([]);
|
|
|
|
const result = await client.getBondData('INVALID');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getBondMarketData', () => {
|
|
it('возвращает рыночные данные облигации из marketdata таблицы', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable.mockReturnValueOnce([{ SECID: 'SU26238RMFS4', BOARDID: 'TQCB', LAST: '98.5', BID: '98', OFFER: '99', YIELD: '7.5', DURATION: '1500', VOLTODAY: '1000', VALTODAY: '98500', NUMTRADES: '50', TRADINGSTATUS: 'T', UPDATETIME: '10:30:00' }]);
|
|
|
|
const result = await client.getBondMarketData('SU26238RMFS4');
|
|
|
|
expect(result).toMatchObject({ secid: 'SU26238RMFS4', last: 98.5, bid: 98, offer: 99, yield: 7.5 });
|
|
});
|
|
|
|
it('возвращает null если marketdata не найдена', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable.mockReturnValueOnce([]);
|
|
|
|
const result = await client.getBondMarketData('INVALID');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getBondPositionDataBatch', () => {
|
|
it('возвращает массив позиций по облигациям', async () => {
|
|
request.mockResolvedValue({});
|
|
extractTable
|
|
.mockReturnValueOnce([
|
|
{ SECID: 'SU26238RMFS4', BOARDID: 'TQCB', SHORTNAME: 'ОФЗ 26238', COUPONVALUE: '34.5', COUPONPERCENT: '7', NEXTCOUPON: '2025-01-15', MATDATE: '2041-05-15', FACEVALUE: '1000', ISIN: 'RU000A1038T7' },
|
|
])
|
|
.mockReturnValueOnce([
|
|
{ SECID: 'SU26238RMFS4', BOARDID: 'TQCB', LAST: '98.5', YIELD: '7.5', DURATION: '1500', BID: '98', OFFER: '99' },
|
|
]);
|
|
|
|
const results = await client.getBondPositionDataBatch(['SU26238RMFS4']);
|
|
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0].secid).toBe('SU26238RMFS4');
|
|
expect(results[0].price).toBe(98.5);
|
|
});
|
|
});
|
|
});
|