feat(events): support date range filtering
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import type { Server } from 'node:http';
|
||||
import request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { configureApp } from '../src/main';
|
||||
import { TbankAccessService } from '../src/tbank/tbank-access.service';
|
||||
import { TbankClient } from '../src/tbank/tbank.client';
|
||||
import { MoexClient } from '../src/tbank/moex.client';
|
||||
|
||||
describe('Upcoming events date filter HTTP boundary', () => {
|
||||
let app: INestApplication<Server>;
|
||||
const getPortfolio = jest.fn();
|
||||
const token = new JwtService().sign(
|
||||
{ sub: 'account-owner', type: 'access' },
|
||||
{ secret: process.env.JWT_SECRET },
|
||||
);
|
||||
beforeAll(async () => {
|
||||
const module = await Test.createTestingModule({ imports: [AppModule] })
|
||||
.overrideProvider(TbankAccessService)
|
||||
.useValue({
|
||||
withAccount: (
|
||||
_user: string,
|
||||
_id: string,
|
||||
handler: (ctx: unknown) => unknown,
|
||||
) => handler({ token: 'unused' }),
|
||||
withSupportedAccounts: (
|
||||
_user: string,
|
||||
handler: (ctx: unknown) => unknown,
|
||||
) =>
|
||||
handler({
|
||||
token: 'unused',
|
||||
accounts: [
|
||||
{ id: 'account', name: 'Main' },
|
||||
{ id: 'second', name: 'Second' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
.overrideProvider(TbankClient)
|
||||
.useValue({
|
||||
getPortfolio,
|
||||
getInstrumentByFigi: () => Promise.resolve(null),
|
||||
})
|
||||
.overrideProvider(MoexClient)
|
||||
.useValue({
|
||||
bondEvents: () =>
|
||||
Promise.resolve([
|
||||
{ type: 'coupon', date: '2099-02-01', value: '2', currency: 'RUB' },
|
||||
{ type: 'offer', date: '2099-02-28' },
|
||||
{ type: 'offer', date: '2099-03-01' },
|
||||
]),
|
||||
})
|
||||
.compile();
|
||||
app = module.createNestApplication();
|
||||
configureApp(app);
|
||||
await app.init();
|
||||
});
|
||||
beforeEach(() => {
|
||||
getPortfolio.mockReset().mockResolvedValue({
|
||||
positions: [
|
||||
{
|
||||
figi: 'B',
|
||||
ticker: 'BOND',
|
||||
instrumentType: 'bond',
|
||||
quantity: { units: 3 },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
afterAll(() => app.close());
|
||||
|
||||
describe.each(['account', 'all'])('%s account scope', (scope) => {
|
||||
it('returns only the requested inclusive period and matching totals', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.get(
|
||||
`/api/v1/brokerage-accounts/${scope}/events?from=2099-02-01&to=2099-02-28`,
|
||||
)
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(200);
|
||||
expect(response.body).toMatchObject({
|
||||
accountId: scope,
|
||||
events:
|
||||
scope === 'all'
|
||||
? [
|
||||
{ date: '2099-02-01', account: { id: 'account' } },
|
||||
{ date: '2099-02-01', account: { id: 'second' } },
|
||||
{ date: '2099-02-28', account: { id: 'account' } },
|
||||
{ date: '2099-02-28', account: { id: 'second' } },
|
||||
]
|
||||
: [{ date: '2099-02-01' }, { date: '2099-02-28' }],
|
||||
incomeTotalsByCurrency: [
|
||||
{ currency: 'RUB', value: scope === 'all' ? '12' : '6' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it.each([
|
||||
'from=not-a-date',
|
||||
'from=2099-02-30',
|
||||
'to=2099-13-01',
|
||||
'from=2099-02-01T00:00:00Z',
|
||||
'from=2099-02-28&to=2099-02-01',
|
||||
])('rejects invalid dates before upstream access: %s', async (query) => {
|
||||
await request(app.getHttpServer())
|
||||
.get(`/api/v1/brokerage-accounts/${scope}/events?${query}`)
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(400);
|
||||
expect(getPortfolio).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user