feat(tests): update Alpaca API tests to include range parameters and improve stock database cleanup
Run Tests / test (push) Failing after 8s

- Modified Alpaca Historical Bars tests to include range parameters in API requests.
- Updated test descriptions for clarity.
- Added cleanup step to delete test ticker after verification in stock database tests.
- Adjusted Vitest configuration to exclude test files from coverage.
This commit is contained in:
2026-05-14 16:46:28 +02:00
parent cc22174b78
commit 15e49cb0f9
16 changed files with 187 additions and 158 deletions
+5 -1
View File
@@ -12,9 +12,13 @@ export async function loader() {
try {
const positions = await alpaca.getPositions();
return Response.json(
positions.map((p: { symbol: string; qty: string; avg_entry_price: string; current_price: string }) => ({
positions.map((p: { symbol: string; qty: string; avg_entry_price: string; current_price: string; market_value: string; unrealized_pl: string }) => ({
ticker: p.symbol,
qty: parseFloat(p.qty),
avg_entry_price: parseFloat(p.avg_entry_price),
current_price: parseFloat(p.current_price),
market_value: parseFloat(p.market_value),
unrealized_pl: parseFloat(p.unrealized_pl),
}))
);
} catch (error) {
+21 -25
View File
@@ -12,9 +12,8 @@ export async function loader({ request, params }: { request: Request; params: {
const ticker = params.ticker?.toUpperCase();
const url = new URL(request.url);
const timeframe = url.searchParams.get("timeframe") || "1D";
const limit = parseInt(url.searchParams.get("limit") || "30", 10);
const range = url.searchParams.get("range") || "1M"; // 1D, 1W, 1M, 3M, 1Y, 3Y, ALL
console.log(`API quote/${ticker}: loader called with timeframe=${timeframe}, limit=${limit}`);
if (!ticker) {
return Response.json({ error: "Ticker is required" }, { status: 400 });
}
@@ -25,52 +24,51 @@ export async function loader({ request, params }: { request: Request; params: {
try {
const trade = await alpaca.getLatestTrade(ticker);
price = (trade as { Price?: number }).Price || 0;
console.log(`API quote/${ticker}: latest trade price = ${price}`);
} catch (tradeErr) {
console.error(`API quote/${ticker}: getLatestTrade failed`, tradeErr);
}
// Calculate start date based on timeframe
// Calculate start date based on range
const startDate = new Date();
const isIntraday = ["1Min", "5Min", "15Min", "30Min", "1H"].includes(timeframe);
if (timeframe === "1D") {
startDate.setDate(startDate.getDate() - Math.min(limit, 30));
} else if (timeframe === "1W") {
startDate.setDate(startDate.getDate() - (limit * 7));
} else if (timeframe === "1M") {
startDate.setMonth(startDate.getMonth() - limit);
if (range === "1D") {
startDate.setDate(startDate.getDate() - 1);
} else if (range === "1W") {
startDate.setDate(startDate.getDate() - 7);
} else if (range === "1M") {
startDate.setMonth(startDate.getMonth() - 1);
} else if (range === "3M") {
startDate.setMonth(startDate.getMonth() - 3);
} else if (range === "1Y") {
startDate.setFullYear(startDate.getFullYear() - 1);
} else if (range === "3Y") {
startDate.setFullYear(startDate.getFullYear() - 3);
} else if (range === "ALL") {
startDate.setFullYear(startDate.getFullYear() - 10); // Max 10 years
} else if (isIntraday) {
startDate.setDate(startDate.getDate() - Math.floor(limit / 5));
startDate.setDate(startDate.getDate() - 30); // Default 30 days for intraday
}
const barsOptions: any = { timeframe, limit };
if (timeframe !== "1Min" && timeframe !== "5Min") {
const barsOptions: any = { timeframe, limit: 1000 }; // High limit for time range
if (!isIntraday && range !== "ALL") {
barsOptions.start = startDate.toISOString().split('T')[0];
} else if (!isIntraday) {
barsOptions.start = startDate.toISOString().split('T')[0];
}
console.log(`API quote/${ticker}: calling getBarsV2 with timeframe=${timeframe}, limit=${limit}`);
const bars = await alpaca.getBarsV2(ticker, barsOptions);
console.log(`API quote/${ticker}: getBarsV2 returned`, typeof bars, bars?.constructor?.name);
// Convert async generator to array
// Alpaca v2 API returns AlpacaBar with capitalized property names
const barsArray = [];
try {
for await (const bar of bars) {
console.log(`API quote/${ticker}: received bar =`, JSON.stringify(bar));
barsArray.push(bar);
}
} catch (genErr) {
console.error(`API quote/${ticker}: error iterating bars`, genErr);
}
console.log(`API quote/${ticker}: raw bars count = ${barsArray.length}`);
if (barsArray.length > 0) {
console.log(`API quote/${ticker}: first bar =`, JSON.stringify(barsArray[0]));
} else {
console.log(`API quote/${ticker}: no bars returned from Alpaca, generator may be empty`);
}
// Transform to chart format
const transformedBars = barsArray.map((bar: any) => {
@@ -91,8 +89,6 @@ export async function loader({ request, params }: { request: Request; params: {
v: volume,
};
}).filter((bar: any) => bar.o > 0 && bar.h > 0 && bar.l > 0 && bar.c > 0);
console.log(`API quote/${ticker}: returning ${transformedBars.length} bars`);
return Response.json({
ticker,