phase-10.5: test case fixes and updated postman collection

This commit is contained in:
saikiranvella
2026-06-12 00:47:41 -04:00
parent 65907a9b8d
commit 6cb4c93a0e
8 changed files with 524 additions and 668 deletions
@@ -1,7 +1,7 @@
{
"info": {
"name": "Market Screener API",
"description": "Full test suite for the market-screener Fastify server.\n\nBase URL is stored in the `baseUrl` collection variable (default: http://localhost:3000).\n\nWorkflow order for a clean session:\n1. Health Check\n2. Screen Tickers (creates results to inspect)\n3. Get Market Context\n4. Get Catalysts\n5. Add Holdings Get Portfolio\n6. Create Market Call Get Call Calendar\n7. Analyze\n8. Cleanup (delete holding, delete call)",
"description": "Full test suite for the market-screener Fastify server.\n\nBase URL is stored in the `baseUrl` collection variable (default: http://localhost:3000).\n\nWorkflow order for a clean session:\n1. Health Check\n2. Screen Tickers (creates results to inspect)\n3. Get Market Context\n4. Get Catalysts\n5. Add Holdings \u2192 Get Portfolio\n6. Create Market Call \u2192 Get Call \u2192 Calendar\n7. Analyze\n8. Cleanup (delete holding, delete call)",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
@@ -15,6 +15,11 @@
"value": "",
"type": "string",
"description": "Set automatically by the Create Market Call test script"
},
{
"key": "jwt",
"value": "",
"type": "string"
}
],
"item": [
@@ -49,11 +54,16 @@
"name": "Screener",
"item": [
{
"name": "Screen Mixed (STOCK + ETF + BOND)",
"name": "Screen \u2014 Mixed (STOCK + ETF + BOND)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/screen",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": [\"AAPL\", \"MSFT\", \"GOOGL\", \"VOO\", \"AGG\"]\n}"
@@ -90,7 +100,7 @@
"pm.test('Each stock has a signal', () => {",
" pm.response.json().STOCK.forEach(r => {",
" pm.expect(r.signal).to.be.oneOf([",
" ' Strong Buy', ' Momentum', '⚠️ Speculation', '🔄 Neutral', ' Avoid'",
" '\u2705 Strong Buy', '\u26a1 Momentum', '\u26a0\ufe0f Speculation', '\ud83d\udd04 Neutral', '\u274c Avoid'",
" ]);",
" });",
"});"
@@ -100,11 +110,16 @@
]
},
{
"name": "Screen Tech Stocks (tests TECHNOLOGY sector override)",
"name": "Screen \u2014 Tech Stocks (tests TECHNOLOGY sector override)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/screen",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": [\"NVDA\", \"META\", \"AMZN\", \"TSLA\"]\n}"
@@ -140,11 +155,16 @@
]
},
{
"name": "Screen REIT (tests P/FFO scoring path)",
"name": "Screen \u2014 REIT (tests P/FFO scoring path)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/screen",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": [\"O\", \"VICI\", \"PLD\"]\n}"
@@ -169,11 +189,16 @@
]
},
{
"name": "Screen Validation: empty tickers (expect 400)",
"name": "Screen \u2014 Validation: empty tickers (expect 400)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/screen",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": []\n}"
@@ -192,11 +217,16 @@
]
},
{
"name": "Screen Validation: over 50 tickers (expect 400)",
"name": "Screen \u2014 Validation: over 50 tickers (expect 400)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/screen",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": [\"A\",\"B\",\"C\",\"D\",\"E\",\"F\",\"G\",\"H\",\"I\",\"J\",\"K\",\"L\",\"M\",\"N\",\"O\",\"P\",\"Q\",\"R\",\"S\",\"T\",\"U\",\"V\",\"W\",\"X\",\"Y\",\"Z\",\"AA\",\"BB\",\"CC\",\"DD\",\"EE\",\"FF\",\"GG\",\"HH\",\"II\",\"JJ\",\"KK\",\"LL\",\"MM\",\"NN\",\"OO\",\"PP\",\"QQ\",\"RR\",\"SS\",\"TT\",\"UU\",\"VV\",\"WW\",\"XX\",\"YY\"]\n}"
@@ -277,11 +307,16 @@
"name": "Portfolio",
"item": [
{
"name": "Add Holding AAPL",
"name": "Add Holding \u2014 AAPL",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/finance/holdings",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"ticker\": \"AAPL\",\n \"shares\": 10,\n \"costBasis\": 150.00,\n \"type\": \"stock\",\n \"source\": \"Robinhood\"\n}"
@@ -307,11 +342,16 @@
]
},
{
"name": "Add Holding VOO (ETF)",
"name": "Add Holding \u2014 VOO (ETF)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/finance/holdings",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"ticker\": \"VOO\",\n \"shares\": 5,\n \"costBasis\": 420.00,\n \"type\": \"etf\",\n \"source\": \"Vanguard\"\n}"
@@ -329,16 +369,21 @@
]
},
{
"name": "Add Holding BTC-USD (Crypto, no scoring)",
"name": "Add Holding \u2014 BTC-USD (Crypto, no scoring)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/finance/holdings",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"ticker\": \"BTC-USD\",\n \"shares\": 0.1,\n \"costBasis\": 50000,\n \"type\": \"crypto\",\n \"source\": \"Coinbase\"\n}"
},
"description": "Crypto is priced via Yahoo but not fundamentally scored. Advice column shows '' for signal."
"description": "Crypto is priced via Yahoo but not fundamentally scored. Advice column shows '\u2014' for signal."
},
"event": [
{
@@ -352,11 +397,16 @@
]
},
{
"name": "Add Holding Validation: missing shares (expect 400)",
"name": "Add Holding \u2014 Validation: missing shares (expect 400)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/finance/holdings",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"ticker\": \"MSFT\"\n}"
@@ -407,7 +457,7 @@
]
},
{
"name": "Remove Holding AAPL",
"name": "Remove Holding \u2014 AAPL",
"request": {
"method": "DELETE",
"url": "{{baseUrl}}/api/finance/holdings/AAPL",
@@ -426,7 +476,7 @@
]
},
{
"name": "Remove Holding Non-existent (expect 404)",
"name": "Remove Holding \u2014 Non-existent (expect 404)",
"request": {
"method": "DELETE",
"url": "{{baseUrl}}/api/finance/holdings/ZZZZZZ",
@@ -472,7 +522,12 @@
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/calls",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"AI Infrastructure Supercycle\",\n \"quarter\": \"Q3 2025\",\n \"thesis\": \"Hyperscaler capex remains elevated through 2026 driven by LLM training demand. NVDA, MSFT and AMD are the primary beneficiaries. Entry here as NVDA pulled back 15% from high.\",\n \"tickers\": [\"NVDA\", \"MSFT\", \"AMD\"]\n}"
@@ -504,7 +559,7 @@
"request": {
"method": "GET",
"url": "{{baseUrl}}/api/calls/{{callId}}",
"description": "Fetches the call and re-screens all tickers to show how signal/price has changed since creation.\n\nReturns: original call fields + `current` map of ticker { price, signal, inflatedVerdict, fundamentalVerdict, pe, roe, fcf }.\n\nDepends on {{callId}} being set by the Create Market Call request."
"description": "Fetches the call and re-screens all tickers to show how signal/price has changed since creation.\n\nReturns: original call fields + `current` map of ticker \u2192 { price, signal, inflatedVerdict, fundamentalVerdict, pe, roe, fcf }.\n\nDepends on {{callId}} being set by the Create Market Call request."
},
"event": [
{
@@ -524,7 +579,7 @@
]
},
{
"name": "Get Call Non-existent ID (expect 404)",
"name": "Get Call \u2014 Non-existent ID (expect 404)",
"request": {
"method": "GET",
"url": "{{baseUrl}}/api/calls/00000000-0000-0000-0000-000000000000",
@@ -574,13 +629,16 @@
]
},
{
"name": "Get Earnings Calendar Specific Tickers",
"name": "Get Earnings Calendar \u2014 Specific Tickers",
"request": {
"method": "GET",
"url": {
"raw": "{{baseUrl}}/api/calls/calendar?tickers=AAPL,MSFT",
"query": [
{ "key": "tickers", "value": "AAPL,MSFT" }
{
"key": "tickers",
"value": "AAPL,MSFT"
}
]
},
"description": "Calendar for specific tickers regardless of saved calls."
@@ -602,11 +660,16 @@
]
},
{
"name": "Create Call Validation: short thesis (expect 400)",
"name": "Create Call \u2014 Validation: short thesis (expect 400)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/calls",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"title\": \"Test\",\n \"quarter\": \"Q1\",\n \"thesis\": \"short\",\n \"tickers\": [\"AAPL\"]\n}"
@@ -644,7 +707,7 @@
]
},
{
"name": "Delete Call Already Deleted (expect 404)",
"name": "Delete Call \u2014 Already Deleted (expect 404)",
"request": {
"method": "DELETE",
"url": "{{baseUrl}}/api/calls/{{callId}}",
@@ -671,7 +734,12 @@
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/analyze",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": [\"NVDA\", \"AMD\", \"INTC\"]\n}"
@@ -709,11 +777,16 @@
]
},
{
"name": "Analyze Validation: empty tickers (expect 400)",
"name": "Analyze \u2014 Validation: empty tickers (expect 400)",
"request": {
"method": "POST",
"url": "{{baseUrl}}/api/analyze",
"header": [{ "key": "Content-Type", "value": "application/json" }],
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"tickers\": []\n}"
@@ -732,6 +805,347 @@
]
}
]
},
{
"name": "Screener \u2014 Ticker Detail & Sectors (June 2026)",
"item": [
{
"name": "Signal history (snapshot ledger)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/screen/history/AAPL",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"screen",
"history",
"AAPL"
]
},
"description": "Per-day signal/tier/score history from the signal_snapshots ledger (P0.1)."
}
},
{
"name": "Company profile",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/screen/profile/AAPL",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"screen",
"profile",
"AAPL"
]
},
"description": "Name, description, sector, market cap + analyst targets (mean/high/low, upside). Cached 1h."
}
},
{
"name": "Price chart",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/screen/chart/AAPL?range=6mo",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"screen",
"chart",
"AAPL"
],
"query": [
{
"key": "range",
"value": "6mo"
}
]
},
"description": "Closes for the ticker modal chart. range: 1d|5d|1mo|3mo|6mo|ytd|1y|5y (intraday bars for 1d/5d)."
}
},
{
"name": "Sector pulse",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/screen/sectors",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"screen",
"sectors"
]
},
"description": "Today's % change per sector via SPDR ETFs, sorted best\u2192worst, with leader. Cached 15m."
}
},
{
"name": "Sector drill-down",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/screen/sector/TECHNOLOGY",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"screen",
"sector",
"TECHNOLOGY"
]
},
"description": "Top-10 ETF holdings screened + 3-day sector news. Sectors: TECHNOLOGY, FINANCIAL, ENERGY, HEALTHCARE, COMMUNICATION, CONSUMER_STAPLES, CONSUMER_DISCRETIONARY, REIT. Cached 30m."
}
}
]
},
{
"name": "News & Digest (June 2026)",
"item": [
{
"name": "News for ticker (stored + live merge)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/news/AAPL?days=7&live=1",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"news",
"AAPL"
],
"query": [
{
"key": "days",
"value": "7"
},
{
"key": "live",
"value": "1"
}
]
},
"description": "Stored pipeline stories (EDGAR + PR wires, catalyst-tagged) merged with a live Yahoo search. live=0 for stored only."
}
},
{
"name": "Recent news (all tickers)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/news/recent?limit=50",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"news",
"recent"
],
"query": [
{
"key": "limit",
"value": "50"
}
]
},
"description": ""
}
},
{
"name": "Daily digest (today)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/digest",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"digest"
]
},
"description": "Signal flips vs previous snapshots + news catalysts + M&A stories."
}
},
{
"name": "Daily digest (specific day)",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseUrl}}/api/digest?date=2026-06-12",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"digest"
],
"query": [
{
"key": "date",
"value": "2026-06-12"
}
]
},
"description": ""
}
}
]
},
{
"name": "Auth & Watchlist",
"item": [
{
"name": "Register",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/auth/register",
"host": [
"{{baseUrl}}"
],
"path": [
"auth",
"register"
]
},
"description": "Invite code is printed in the server terminal on boot (hidden during tests).",
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"you@example.com\",\n \"password\": \"min-8-chars\",\n \"inviteCode\": \"<printed on server boot>\"\n}"
}
}
},
{
"name": "Login",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"url": {
"raw": "{{baseUrl}}/auth/login",
"host": [
"{{baseUrl}}"
],
"path": [
"auth",
"login"
]
},
"description": "Returns { token } \u2014 save as {{jwt}} collection variable.",
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"you@example.com\",\n \"password\": \"min-8-chars\"\n}"
}
}
},
{
"name": "Get watchlist",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{jwt}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/watchlist",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"watchlist"
]
},
"description": ""
}
},
{
"name": "Pin ticker",
"request": {
"method": "POST",
"header": [
{
"key": "Authorization",
"value": "Bearer {{jwt}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/watchlist/AAPL",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"watchlist",
"AAPL"
]
},
"description": ""
}
},
{
"name": "Unpin ticker",
"request": {
"method": "DELETE",
"header": [
{
"key": "Authorization",
"value": "Bearer {{jwt}}"
}
],
"url": {
"raw": "{{baseUrl}}/api/watchlist/AAPL",
"host": [
"{{baseUrl}}"
],
"path": [
"api",
"watchlist",
"AAPL"
]
},
"description": ""
}
}
]
}
]
}
}