feat: add stock screener
This commit is contained in:
@@ -15,6 +15,7 @@ import { configureApp } from '../src/main';
|
||||
import { StockCatalogService } from '../src/modules/investments/instruments/stocks/application/stock-catalog.service';
|
||||
import { StockIncomeService } from '../src/modules/investments/instruments/stocks/application/stock-income.service';
|
||||
import { StockMarketService } from '../src/modules/investments/instruments/stocks/application/stock-market.service';
|
||||
import { StockScreenerService } from '../src/modules/investments/instruments/stocks/application/stock-screener.service';
|
||||
|
||||
const uid = 'e6123145-9665-43e0-8413-cd61b8aa9b13';
|
||||
describe('Stock HTTP contract', () => {
|
||||
@@ -25,6 +26,7 @@ describe('Stock HTTP contract', () => {
|
||||
search: jest.fn(),
|
||||
candles: jest.fn(),
|
||||
};
|
||||
const screener = { page: jest.fn(), search: jest.fn() };
|
||||
const token = new JwtService().sign(
|
||||
{ sub: 'stock-reader', type: 'access' },
|
||||
{ secret: process.env.JWT_SECRET },
|
||||
@@ -37,6 +39,8 @@ describe('Stock HTTP contract', () => {
|
||||
.useValue(stocks)
|
||||
.overrideProvider(StockIncomeService)
|
||||
.useValue(stocks)
|
||||
.overrideProvider(StockScreenerService)
|
||||
.useValue(screener)
|
||||
.compile();
|
||||
app = module.createNestApplication();
|
||||
configureApp(app);
|
||||
@@ -51,12 +55,55 @@ describe('Stock HTTP contract', () => {
|
||||
});
|
||||
stocks.search.mockResolvedValue([]);
|
||||
stocks.getByTicker.mockResolvedValue({ instrumentUid: uid, slug: 'SBERP' });
|
||||
screener.search.mockResolvedValue({ asOf: '2026-10-10T12:00:00.000Z', hasNext: false, items: [], page: 1, searchId: 'search-id' });
|
||||
});
|
||||
afterAll(() => app.close());
|
||||
it('requires authentication before invoking the use case', async () => {
|
||||
await request(app.getHttpServer()).get(`/api/v1/stocks/${uid}`).expect(401);
|
||||
expect(stocks.get).not.toHaveBeenCalled();
|
||||
});
|
||||
it.each([
|
||||
[() => request(app.getHttpServer()).post('/api/v1/stocks/screener/search'), 'post'],
|
||||
[() => request(app.getHttpServer()).get('/api/v1/stocks/screener/search/search-id?page=1'), 'get'],
|
||||
])('requires authentication for screener route', async (send) => {
|
||||
await send().expect(401);
|
||||
expect(screener.search).not.toHaveBeenCalled();
|
||||
expect(screener.page).not.toHaveBeenCalled();
|
||||
});
|
||||
it('validates screener input and returns raw snapshot pages', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.post('/api/v1/stocks/screener/search')
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.send({ query: ' ', unknown: 'value' })
|
||||
.expect(400);
|
||||
expect(screener.search).not.toHaveBeenCalled();
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/api/v1/stocks/screener/search')
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.send({ query: '' })
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({ asOf: '2026-10-10T12:00:00.000Z', hasNext: false, items: [], page: 1, searchId: 'search-id' });
|
||||
expect(screener.search).toHaveBeenCalledWith('stock-reader', {});
|
||||
});
|
||||
it.each([
|
||||
'/api/v1/stocks/screener/search/search-id',
|
||||
'/api/v1/stocks/screener/search/search-id?page=0',
|
||||
'/api/v1/stocks/screener/search/search-id?page=one',
|
||||
])('validates required screener page on %s', async (path) => {
|
||||
await request(app.getHttpServer())
|
||||
.get(path)
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(400);
|
||||
expect(screener.page).not.toHaveBeenCalled();
|
||||
});
|
||||
it('reads a screener snapshot page with the verified identity', async () => {
|
||||
await request(app.getHttpServer())
|
||||
.get('/api/v1/stocks/screener/search/search-id?page=2')
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
.expect(200);
|
||||
expect(screener.page).toHaveBeenCalledWith('stock-reader', 'search-id', 2);
|
||||
});
|
||||
it.each([
|
||||
'/stocks/not-a-uid',
|
||||
'/stocks/by-ticker/%20',
|
||||
|
||||
Reference in New Issue
Block a user