moex-vibe/apps/backend/src/modules/tbank/tbank.controller.spec.ts
2026-06-22 06:41:37 +03:00

90 lines
3.4 KiB
TypeScript

import { ROLES_KEY } from '../auth/decorators/roles.decorator';
import { ApiResponse } from '../../common/dto/api-response.dto';
import { TBankController } from './tbank.controller';
import { BrokerAccountsService } from './services/broker-accounts.service';
import { BrokerEventsService } from './services/broker-events.service';
import { BrokerOperationSyncService } from './services/broker-operation-sync.service';
import { BrokerOperationsService } from './services/broker-operations.service';
import { BrokerPortfolioService } from './services/broker-portfolio.service';
describe('TBankController', () => {
const accounts = { findAll: vi.fn() } as unknown as BrokerAccountsService;
const portfolio = { getPortfolio: vi.fn() } as unknown as BrokerPortfolioService;
const events = { getEvents: vi.fn() } as unknown as BrokerEventsService;
const operations = { getOperations: vi.fn() } as unknown as BrokerOperationsService;
const sync = { syncAccount: vi.fn() } as unknown as BrokerOperationSyncService;
beforeEach(() => {
vi.clearAllMocks();
});
it('allows authenticated users to access broker endpoints', () => {
expect(Reflect.getMetadata(ROLES_KEY, TBankController)).toEqual(['user']);
});
it('returns accounts in a single API envelope', async () => {
vi.mocked(accounts.findAll).mockResolvedValueOnce({
data: [
{
id: 'acc-1',
type: 'brokerage',
name: 'Broker',
status: 'ACCOUNT_STATUS_OPEN',
openedAt: null,
accessLevel: null,
},
],
meta: { fromCache: true, cachedAt: '2026-06-17T00:00:00.000Z' },
});
const controller = new TBankController(accounts, portfolio, events, operations, sync);
const response = await controller.getAccounts();
expect(response).toBeInstanceOf(ApiResponse);
expect(response.data).toHaveLength(1);
expect(response.meta).toEqual({ fromCache: true, cachedAt: '2026-06-17T00:00:00.000Z' });
});
it('exposes a sync trigger for durable operation history', async () => {
vi.mocked(sync.syncAccount).mockResolvedValueOnce({ upserted: 2 });
const controller = new TBankController(accounts, portfolio, events, operations, sync);
const response = await controller.syncOperations('acc-1', {
from: '2026-06-01T00:00:00.000Z',
to: '2026-06-17T00:00:00.000Z',
});
expect(sync.syncAccount).toHaveBeenCalledWith('acc-1', {
from: '2026-06-01T00:00:00.000Z',
to: '2026-06-17T00:00:00.000Z',
});
expect(response.data).toEqual({ upserted: 2 });
});
it('forwards events query and wraps response', async () => {
const eventsData = {
items: [],
summary: {
eventCount: 0,
nearestEventDate: null,
totalEstimatedCashflow: 0,
dividendsTotal: 0,
couponsTotal: 0,
principalRepaymentTotal: 0,
},
asOf: '2026-06-22T00:00:00.000Z',
};
vi.mocked(events.getEvents).mockResolvedValueOnce({
data: eventsData,
meta: { fromCache: false, cachedAt: '2026-06-22T00:00:00.000Z' },
});
const controller = new TBankController(accounts, portfolio, events, operations, sync);
const response = await controller.getEvents('acc-1', { from: '2026-06-22', to: '2026-07-29' });
expect(events.getEvents).toHaveBeenCalledWith('acc-1', '2026-06-22', '2026-07-29');
expect(response).toBeInstanceOf(ApiResponse);
expect(response.data).toEqual(eventsData);
});
});