test: split moex live integration checks
This commit is contained in:
parent
bc2d2af141
commit
c994b6a2fb
@ -8,8 +8,9 @@
|
||||
"start:dev": "nest start --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"lint": "eslint \"{src,test}/**/*.ts\"",
|
||||
"test": "VITE_CJS_IGNORE_WARNING=1 vitest run",
|
||||
"test:watch": "vitest"
|
||||
"test": "VITE_CJS_IGNORE_WARNING=1 vitest run --exclude \"src/**/*.integration.spec.ts\"",
|
||||
"test:watch": "vitest --exclude \"src/**/*.integration.spec.ts\"",
|
||||
"test:integration": "MOEX_LIVE_TESTS=1 VITE_CJS_IGNORE_WARNING=1 vitest run \"src/**/*.integration.spec.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@libsql/client": "^0.17.3",
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
import 'reflect-metadata';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { MoexClientService } from './moex-client.service';
|
||||
import configuration from '../../config/configuration';
|
||||
|
||||
describe.skipIf(process.env.MOEX_LIVE_TESTS !== '1')(
|
||||
'MoexClientService live MOEX integration',
|
||||
() => {
|
||||
let service: MoexClientService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [ConfigModule.forRoot({ load: [configuration] })],
|
||||
providers: [MoexClientService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<MoexClientService>(MoexClientService);
|
||||
});
|
||||
|
||||
it('возвращает результаты поиска для SBER из live MOEX', async () => {
|
||||
const results = await service.searchSecurities('SBER');
|
||||
|
||||
expect(results.length).toBeGreaterThan(0);
|
||||
expect(results[0].secid).toBeDefined();
|
||||
}, 15000);
|
||||
|
||||
it('возвращает рыночные данные SBER из live MOEX', async () => {
|
||||
const data = await service.getShareMarketData('SBER');
|
||||
|
||||
expect(data).toBeDefined();
|
||||
expect(data!.secid).toBe('SBER');
|
||||
}, 15000);
|
||||
},
|
||||
);
|
||||
@ -1,38 +1,186 @@
|
||||
import 'reflect-metadata';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import axios from 'axios';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { MoexClientService } from './moex-client.service';
|
||||
import configuration from '../../config/configuration';
|
||||
|
||||
vi.mock('axios', () => ({
|
||||
default: {
|
||||
create: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('MoexClientService', () => {
|
||||
let service: MoexClientService;
|
||||
let getMock: ReturnType<typeof vi.fn>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [ConfigModule.forRoot({ load: [configuration] })],
|
||||
providers: [MoexClientService],
|
||||
}).compile();
|
||||
beforeEach(() => {
|
||||
getMock = vi.fn();
|
||||
vi.mocked(axios.create).mockReturnValue({ get: getMock } as never);
|
||||
|
||||
service = module.get<MoexClientService>(MoexClientService);
|
||||
service = new MoexClientService({
|
||||
get: vi.fn((key: string, fallback?: unknown) => {
|
||||
const values: Record<string, unknown> = {
|
||||
'app.moex.baseUrl': 'https://iss.moex.test/iss',
|
||||
'app.moex.circuitBreakerThreshold': 5,
|
||||
'app.moex.circuitBreakerResetSeconds': 30,
|
||||
'app.moex.rateLimit': 10,
|
||||
};
|
||||
return values[key] ?? fallback;
|
||||
}),
|
||||
} as unknown as ConfigService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
it('создаётся с настроенным MOEX client', () => {
|
||||
expect(service).toBeDefined();
|
||||
expect(axios.create).toHaveBeenCalledWith({
|
||||
baseURL: 'https://iss.moex.test/iss',
|
||||
timeout: 10000,
|
||||
paramsSerializer: { indexes: null },
|
||||
});
|
||||
});
|
||||
|
||||
it('нормализует результаты поиска из ISS table format', async () => {
|
||||
getMock.mockResolvedValueOnce({
|
||||
data: {
|
||||
securities: {
|
||||
columns: [
|
||||
'secid',
|
||||
'isin',
|
||||
'name',
|
||||
'shortName',
|
||||
'latName',
|
||||
'listLevel',
|
||||
'issuesize',
|
||||
'facevalue',
|
||||
'faceunit',
|
||||
'issuedate',
|
||||
'typename',
|
||||
'group',
|
||||
'type',
|
||||
'isqualifiedinvestors',
|
||||
'morningsession',
|
||||
'eveningsession',
|
||||
],
|
||||
data: [
|
||||
[
|
||||
'SBER',
|
||||
'RU0009029540',
|
||||
'Сбербанк России ПАО ао',
|
||||
'Сбербанк',
|
||||
'Sberbank',
|
||||
'1',
|
||||
'21586948000',
|
||||
'3',
|
||||
'SUR',
|
||||
'2007-07-20',
|
||||
'Акция обыкновенная',
|
||||
'stock_shares',
|
||||
'common_share',
|
||||
'0',
|
||||
'1',
|
||||
'1',
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('searchSecurities', () => {
|
||||
it('should return results for SBER query', async () => {
|
||||
const results = await service.searchSecurities('SBER');
|
||||
expect(results.length).toBeGreaterThan(0);
|
||||
expect(results[0].secid).toBeDefined();
|
||||
}, 15000);
|
||||
|
||||
expect(getMock).toHaveBeenCalledWith('/securities.json', {
|
||||
params: { q: 'SBER', 'iss.meta': 'off' },
|
||||
});
|
||||
expect(results).toEqual([
|
||||
{
|
||||
secid: 'SBER',
|
||||
isin: 'RU0009029540',
|
||||
name: 'Сбербанк России ПАО ао',
|
||||
shortName: 'Сбербанк',
|
||||
latName: 'Sberbank',
|
||||
listLevel: 1,
|
||||
issueSize: 21586948000,
|
||||
faceValue: 3,
|
||||
faceUnit: 'SUR',
|
||||
issueDate: '2007-07-20',
|
||||
typeName: 'Акция обыкновенная',
|
||||
group: 'stock_shares',
|
||||
type: 'common_share',
|
||||
isQualifiedInvestors: false,
|
||||
morningSession: true,
|
||||
eveningSession: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('нормализует market data акции без live MOEX запроса', async () => {
|
||||
getMock.mockResolvedValueOnce({
|
||||
data: {
|
||||
securities: {
|
||||
columns: ['SECID', 'BOARDID', 'SHORTNAME', 'PREVPRICE'],
|
||||
data: [['SBER', 'TQBR', 'Сбербанк', '320.10']],
|
||||
},
|
||||
marketdata: {
|
||||
columns: [
|
||||
'SECID',
|
||||
'BOARDID',
|
||||
'BID',
|
||||
'OFFER',
|
||||
'OPEN',
|
||||
'LOW',
|
||||
'HIGH',
|
||||
'LAST',
|
||||
'LASTCHANGE',
|
||||
'LASTCHANGEPRCNT',
|
||||
'VOLTODAY',
|
||||
'VALTODAY',
|
||||
'WAPRICE',
|
||||
'NUMTRADES',
|
||||
'ISSUECAPITALIZATION',
|
||||
'TRADINGSTATUS',
|
||||
'UPDATETIME',
|
||||
],
|
||||
data: [
|
||||
[
|
||||
'SBER',
|
||||
'TQBR',
|
||||
'321',
|
||||
'322',
|
||||
'320',
|
||||
'319',
|
||||
'323',
|
||||
'322.35',
|
||||
'1.15',
|
||||
'0.36',
|
||||
'1925163',
|
||||
'620184479',
|
||||
'321.9',
|
||||
'12345',
|
||||
'6958336818320',
|
||||
'T',
|
||||
'10:30:00',
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('getShareMarketData', () => {
|
||||
it('should return market data for SBER', async () => {
|
||||
const data = await service.getShareMarketData('SBER');
|
||||
expect(data).toBeDefined();
|
||||
expect(data!.secid).toBe('SBER');
|
||||
}, 15000);
|
||||
|
||||
expect(getMock).toHaveBeenCalledWith('/engines/stock/markets/shares/securities/SBER.json', {
|
||||
params: { boards: 'TQBR', 'iss.meta': 'off' },
|
||||
});
|
||||
expect(data).toMatchObject({
|
||||
secid: 'SBER',
|
||||
boardid: 'TQBR',
|
||||
shortName: 'Сбербанк',
|
||||
last: 322.35,
|
||||
lastChange: 1.15,
|
||||
lastChangePrcnt: 0.36,
|
||||
volume: 1925163,
|
||||
value: 620184479,
|
||||
issueCapitalization: 6958336818320,
|
||||
tradingStatus: 'T',
|
||||
updateTime: '10:30:00',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user