Add paginated responses (items/total/skip/limit) to:
- GET /api/data/stocks/{ticker}/prices (default limit=365)
- GET /api/data/etfs/{ticker}/prices (default limit=365)
- GET /api/portfolios/{id}/snapshots (default limit=100)
- GET /api/portfolios/{id}/transactions (default limit=50)
Frontend: update snapshot/transaction consumers to handle new response
shape, add "Load more" button to transaction table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.3 KiB
Python
97 lines
3.3 KiB
Python
"""
|
|
E2E tests for data explorer API.
|
|
"""
|
|
from datetime import date
|
|
from fastapi.testclient import TestClient
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models.stock import Stock, ETF, Price, ETFPrice, Sector, Valuation, AssetClass
|
|
|
|
|
|
def _seed_stock(db: Session):
|
|
"""Add test stock data."""
|
|
stock = Stock(
|
|
ticker="005930", name="삼성전자", market="KOSPI",
|
|
close_price=70000, market_cap=400000000000000,
|
|
stock_type="common", base_date=date(2025, 1, 1),
|
|
)
|
|
db.add(stock)
|
|
db.add(Price(ticker="005930", date=date(2025, 1, 2), open=69000, high=71000, low=68500, close=70000, volume=10000000))
|
|
db.add(Price(ticker="005930", date=date(2025, 1, 3), open=70000, high=72000, low=69000, close=71000, volume=12000000))
|
|
db.commit()
|
|
|
|
|
|
def _seed_etf(db: Session):
|
|
"""Add test ETF data."""
|
|
etf = ETF(ticker="069500", name="TIGER 200", asset_class=AssetClass.EQUITY, market="ETF")
|
|
db.add(etf)
|
|
db.add(ETFPrice(ticker="069500", date=date(2025, 1, 2), close=43000, volume=500000))
|
|
db.add(ETFPrice(ticker="069500", date=date(2025, 1, 3), close=43500, volume=600000))
|
|
db.commit()
|
|
|
|
|
|
def _seed_sector(db: Session):
|
|
db.add(Sector(ticker="005930", sector_code="G45", company_name="삼성전자", sector_name="반도체", base_date=date(2025, 1, 1)))
|
|
db.commit()
|
|
|
|
|
|
def _seed_valuation(db: Session):
|
|
db.add(Valuation(ticker="005930", base_date=date(2025, 1, 1), per=12.5, pbr=1.3, dividend_yield=2.1))
|
|
db.commit()
|
|
|
|
|
|
def test_list_stocks(client: TestClient, auth_headers, db: Session):
|
|
_seed_stock(db)
|
|
resp = client.get("/api/data/stocks", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["total"] >= 1
|
|
assert len(data["items"]) >= 1
|
|
assert data["items"][0]["ticker"] == "005930"
|
|
|
|
|
|
def test_list_stocks_search(client: TestClient, auth_headers, db: Session):
|
|
_seed_stock(db)
|
|
resp = client.get("/api/data/stocks?search=삼성", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["total"] >= 1
|
|
|
|
|
|
def test_stock_prices(client: TestClient, auth_headers, db: Session):
|
|
_seed_stock(db)
|
|
resp = client.get("/api/data/stocks/005930/prices", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert len(data["items"]) == 2
|
|
assert data["total"] == 2
|
|
|
|
|
|
def test_list_etfs(client: TestClient, auth_headers, db: Session):
|
|
_seed_etf(db)
|
|
resp = client.get("/api/data/etfs", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["total"] >= 1
|
|
|
|
|
|
def test_etf_prices(client: TestClient, auth_headers, db: Session):
|
|
_seed_etf(db)
|
|
resp = client.get("/api/data/etfs/069500/prices", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert len(data["items"]) == 2
|
|
assert data["total"] == 2
|
|
|
|
|
|
def test_list_sectors(client: TestClient, auth_headers, db: Session):
|
|
_seed_sector(db)
|
|
resp = client.get("/api/data/sectors", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["total"] >= 1
|
|
|
|
|
|
def test_list_valuations(client: TestClient, auth_headers, db: Session):
|
|
_seed_valuation(db)
|
|
resp = client.get("/api/data/valuations", headers=auth_headers)
|
|
assert resp.status_code == 200
|
|
assert resp.json()["total"] >= 1
|