test(api): align market data contract checks
This commit is contained in:
parent
3d505db8d8
commit
f57f0fc205
@ -64,7 +64,7 @@ function testChartBarsContract() {
|
|||||||
'/api/chart/bars must reject missing symbols',
|
'/api/chart/bars must reject missing symbols',
|
||||||
);
|
);
|
||||||
assertSourceMatches(
|
assertSourceMatches(
|
||||||
/this\.app\.get\('\/api\/chart\/bars'[\s\S]*Alpaca credentials not configured/,
|
/this\.app\.get\('\/api\/chart\/bars'[\s\S]*getUserMarketDataAlpacaCredentials\(authUserId\)[\s\S]*if \(error instanceof MissingServiceConfigError\)[\s\S]*status\(503\)\.json\(\{ error: error\.message \}\)/,
|
||||||
'/api/chart/bars must fail closed when Alpaca credentials are absent',
|
'/api/chart/bars must fail closed when Alpaca credentials are absent',
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -156,26 +156,18 @@ function testFmpProxyContracts() {
|
|||||||
"import { fetchFmpJson, FmpFetchError } from './fmpCache.js';",
|
"import { fetchFmpJson, FmpFetchError } from './fmpCache.js';",
|
||||||
'FMP routes must use the shared cache helper and typed upstream error',
|
'FMP routes must use the shared cache helper and typed upstream error',
|
||||||
);
|
);
|
||||||
assertConfigIncludes(
|
|
||||||
"FMP_API_KEY: process.env.FMP_API_KEY || '',",
|
|
||||||
'FMP config must not silently default to the shared demo key',
|
|
||||||
);
|
|
||||||
assertSourceIncludes(
|
assertSourceIncludes(
|
||||||
"apiKey.toLowerCase() === 'demo'",
|
'User FMP API key is required for research and screener endpoints',
|
||||||
'FMP routes must reject the shared demo key explicitly',
|
'FMP routes must surface an explicit per-user missing-key error',
|
||||||
);
|
|
||||||
assertSourceIncludes(
|
|
||||||
'FMP_API_KEY is required for research and screener endpoints',
|
|
||||||
'FMP routes must surface an explicit missing-key error',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const fetchFmpCalls = apiServerSource.match(/fetchFmpJson\(url\)/g) ?? [];
|
const fetchFmpCalls = apiServerSource.match(/fetchFmpJson\(url\)/g) ?? [];
|
||||||
assert.equal(fetchFmpCalls.length, 4, 'each FMP route must fetch through fetchFmpJson(url)');
|
assert.equal(fetchFmpCalls.length, 4, 'each FMP route must fetch through fetchFmpJson(url)');
|
||||||
|
|
||||||
for (const [route, endpoint, errorMessage] of [
|
for (const [route, endpoint, errorMessage] of [
|
||||||
['/api/research/profile', '/api/v3/profile/${symbol}?apikey=${apiKey}', 'FMP profile fetch failed'],
|
['/api/research/profile', 'https://financialmodelingprep.com/stable/profile?symbol=${encodeURIComponent(symbol)}&apikey=${apiKey}', 'FMP profile fetch failed'],
|
||||||
['/api/research/metrics', '/api/v3/key-metrics/${symbol}?limit=4&apikey=${apiKey}', 'FMP metrics fetch failed'],
|
['/api/research/metrics', 'https://financialmodelingprep.com/stable/key-metrics?symbol=${encodeURIComponent(symbol)}&limit=4&apikey=${apiKey}', 'FMP metrics fetch failed'],
|
||||||
['/api/research/earnings', '/api/v3/historical/earning_calendar/${symbol}?limit=8&apikey=${apiKey}', 'FMP earnings fetch failed'],
|
['/api/research/earnings', 'https://financialmodelingprep.com/stable/earnings-calendar?symbol=${encodeURIComponent(symbol)}&limit=8&apikey=${apiKey}', 'FMP earnings fetch failed'],
|
||||||
]) {
|
]) {
|
||||||
assertSourceMatches(
|
assertSourceMatches(
|
||||||
new RegExp(`this\\.app\\.get\\('${escapeRegExp(route)}'[\\s\\S]*if \\(!symbol\\)[\\s\\S]*status\\(400\\)\\.json\\(\\{ error: 'symbol required' \\}\\)`),
|
new RegExp(`this\\.app\\.get\\('${escapeRegExp(route)}'[\\s\\S]*if \\(!symbol\\)[\\s\\S]*status\\(400\\)\\.json\\(\\{ error: 'symbol required' \\}\\)`),
|
||||||
@ -194,8 +186,8 @@ function testFmpProxyContracts() {
|
|||||||
'/api/research/earnings must normalize to an earnings array wrapper',
|
'/api/research/earnings must normalize to an earnings array wrapper',
|
||||||
);
|
);
|
||||||
assertSourceIncludes(
|
assertSourceIncludes(
|
||||||
'https://financialmodelingprep.com/api/v3/stock-screener?${qs.toString()}',
|
'https://financialmodelingprep.com/stable/company-screener?${qs.toString()}',
|
||||||
'/api/screener must call FMP stock-screener',
|
'/api/screener must call FMP stable company-screener',
|
||||||
);
|
);
|
||||||
assertSourceIncludes(
|
assertSourceIncludes(
|
||||||
'const ALLOWED_SCREENER_SECTORS = new Set([',
|
'const ALLOWED_SCREENER_SECTORS = new Set([',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user