import os import sqlite3 import pytest from fastapi.testclient import TestClient from app.screener.schema import ensure_screener_schema from app.db import init_db @pytest.fixture(autouse=True) def isolated_db_and_auth(tmp_path, monkeypatch): db_path = tmp_path / "stock.db" # 기본 stock DB 스키마 monkeypatch.setenv("STOCK_DB_PATH", str(db_path)) init_db() # screener 스키마 (news_sentiment, krx_master 등) c = sqlite3.connect(db_path) ensure_screener_schema(c) c.close() # WEBAI_API_KEY 활성화 monkeypatch.setenv("WEBAI_API_KEY", "test-secret") @pytest.fixture def client(): from app.main import app return TestClient(app) HEADERS_OK = {"X-WebAI-Key": "test-secret"} def _seed_portfolio(broker="키움", ticker="005930", name="삼성전자", quantity=100, avg_price=75000.0, purchase_price=75500.0): from app.db import add_portfolio_item return add_portfolio_item(broker, ticker, name, quantity, avg_price, purchase_price=purchase_price) def test_webai_portfolio_normal_response_includes_pnl_pct(client, monkeypatch): _seed_portfolio() # current_price 모킹 — profit_rate 4.67% 만들기 from app import main monkeypatch.setattr( main, "get_current_prices_detail", lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "2026-05-15T15:30:00"}} ) r = client.get("/api/webai/portfolio", headers=HEADERS_OK) assert r.status_code == 200 body = r.json() assert len(body["holdings"]) == 1 h = body["holdings"][0] assert h["pnl_pct"] is not None assert abs(h["pnl_pct"] - 0.0467) < 0.0005 # 0.0467 ± rounding def test_webai_portfolio_summary_has_total_pnl_pct(client, monkeypatch): _seed_portfolio() from app import main monkeypatch.setattr( main, "get_current_prices_detail", lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "x"}} ) r = client.get("/api/webai/portfolio", headers=HEADERS_OK) body = r.json() assert "total_pnl_pct" in body["summary"] assert abs(body["summary"]["total_pnl_pct"] - 0.0467) < 0.0005 def test_webai_portfolio_pnl_pct_matches_profit_rate_divided_100(client, monkeypatch): _seed_portfolio() from app import main monkeypatch.setattr( main, "get_current_prices_detail", lambda tickers: {"005930": {"price": 78500.0, "session": "REGULAR", "as_of": "x"}} ) r = client.get("/api/webai/portfolio", headers=HEADERS_OK) h = r.json()["holdings"][0] assert h["pnl_pct"] == round(h["profit_rate"] / 100, 6) def test_webai_portfolio_missing_key_returns_401(client): r = client.get("/api/webai/portfolio") assert r.status_code == 401 assert "X-WebAI-Key" in r.json()["detail"]