201 lines
7.7 KiB
Python
201 lines
7.7 KiB
Python
"""Tests for display mode switching functionality."""
|
|
|
|
from decimal import Decimal
|
|
|
|
import pytest
|
|
|
|
from app.domain.conversions import (
|
|
collateral_to_display_units,
|
|
format_display_quantity,
|
|
get_display_mode_label,
|
|
get_display_mode_options,
|
|
position_to_display_units,
|
|
)
|
|
from app.models.position import create_position
|
|
|
|
|
|
class TestDisplayModeOptions:
|
|
"""Test display mode option helpers."""
|
|
|
|
def test_get_display_mode_options(self):
|
|
"""Test display mode options dictionary."""
|
|
options = get_display_mode_options()
|
|
assert "GLD" in options
|
|
assert "XAU_OZ" in options
|
|
assert "XAU_G" in options
|
|
assert "GCF" in options
|
|
assert options["GLD"] == "GLD Shares"
|
|
assert options["XAU_OZ"] == "Gold Ounces (troy)"
|
|
assert options["XAU_G"] == "Gold Grams"
|
|
assert options["GCF"] == "GC=F Contracts"
|
|
|
|
def test_get_display_mode_label(self):
|
|
"""Test display mode label lookup."""
|
|
assert get_display_mode_label("GLD") == "GLD Shares"
|
|
assert get_display_mode_label("XAU_OZ") == "Gold (Troy Ounces)"
|
|
assert get_display_mode_label("XAU_G") == "Gold (Grams)"
|
|
assert get_display_mode_label("GCF") == "GC=F Contracts"
|
|
assert get_display_mode_label("UNKNOWN") == "UNKNOWN"
|
|
|
|
|
|
class TestFormatDisplayQuantity:
|
|
"""Test quantity formatting for display."""
|
|
|
|
def test_format_shares(self):
|
|
"""Test share formatting (no decimals)."""
|
|
assert format_display_quantity(100.0, "shares") == "100"
|
|
assert format_display_quantity(1234.56, "shares") == "1,235"
|
|
assert format_display_quantity(1000000.0, "shares") == "1,000,000"
|
|
|
|
def test_format_contracts(self):
|
|
"""Test contract formatting (no decimals)."""
|
|
assert format_display_quantity(10.0, "contracts") == "10"
|
|
assert format_display_quantity(1234.56, "contracts") == "1,235"
|
|
|
|
def test_format_ounces(self):
|
|
"""Test ounce formatting (4 decimals)."""
|
|
assert format_display_quantity(100.0, "oz") == "100.0000"
|
|
assert format_display_quantity(9.1576, "oz") == "9.1576"
|
|
assert format_display_quantity(0.123456, "oz") == "0.1235"
|
|
|
|
def test_format_grams(self):
|
|
"""Test gram formatting (2 decimals)."""
|
|
assert format_display_quantity(100.0, "g") == "100.00"
|
|
assert format_display_quantity(284.83, "g") == "284.83"
|
|
assert format_display_quantity(31103.5, "g") == "31,103.50"
|
|
|
|
|
|
class TestPositionToDisplayUnits:
|
|
"""Test position conversion to display units."""
|
|
|
|
def test_gld_shares_in_gld_mode(self):
|
|
"""Test GLD shares displayed as-is in GLD mode."""
|
|
pos = create_position("GLD", Decimal("100"), "shares", Decimal("230"))
|
|
qty, unit = position_to_display_units(pos, "GLD")
|
|
assert qty == Decimal("100")
|
|
assert unit == "shares"
|
|
|
|
def test_gld_shares_in_xau_oz_mode(self):
|
|
"""Test GLD shares converted to ounces in XAU_OZ mode."""
|
|
pos = create_position("GLD", Decimal("100"), "shares", Decimal("230"))
|
|
qty, unit = position_to_display_units(pos, "XAU_OZ")
|
|
assert unit == "oz"
|
|
# Should be ~9.16 oz for 100 shares (depends on date)
|
|
assert Decimal("9") < qty < Decimal("10")
|
|
|
|
def test_gld_shares_in_xau_g_mode(self):
|
|
"""Test GLD shares converted to grams in XAU_G mode."""
|
|
pos = create_position("GLD", Decimal("100"), "shares", Decimal("230"))
|
|
qty, unit = position_to_display_units(pos, "XAU_G")
|
|
assert unit == "g"
|
|
# Should be ~285 g for 100 shares
|
|
assert Decimal("280") < qty < Decimal("290")
|
|
|
|
def test_gld_shares_in_gcf_mode(self):
|
|
"""Test GLD shares converted to contracts in GCF mode."""
|
|
pos = create_position("GLD", Decimal("1000"), "shares", Decimal("230"))
|
|
qty, unit = position_to_display_units(pos, "GCF")
|
|
assert unit == "contracts"
|
|
# Should be ~0.92 contracts for 1000 shares
|
|
assert Decimal("0.9") < qty < Decimal("1.0")
|
|
|
|
def test_xau_oz_in_gld_mode(self):
|
|
"""Test XAU ounces converted to GLD shares in GLD mode."""
|
|
pos = create_position("XAU", Decimal("10"), "oz", Decimal("2150"))
|
|
qty, unit = position_to_display_units(pos, "GLD")
|
|
assert unit == "shares"
|
|
# 10 oz should be ~109 shares
|
|
assert Decimal("100") < qty < Decimal("120")
|
|
|
|
def test_xau_oz_in_xau_g_mode(self):
|
|
"""Test XAU ounces converted to grams in XAU_G mode."""
|
|
pos = create_position("XAU", Decimal("10"), "oz", Decimal("2150"))
|
|
qty, unit = position_to_display_units(pos, "XAU_G")
|
|
assert unit == "g"
|
|
# 10 oz = 311.035 g
|
|
assert qty == Decimal("311.035")
|
|
|
|
def test_gcf_contracts_in_xau_oz_mode(self):
|
|
"""Test GC=F contracts converted to ounces in XAU_OZ mode."""
|
|
pos = create_position("GC=F", Decimal("1"), "contracts", Decimal("215000"))
|
|
qty, unit = position_to_display_units(pos, "XAU_OZ")
|
|
assert unit == "oz"
|
|
# 1 contract = 100 oz
|
|
assert qty == Decimal("100")
|
|
|
|
def test_gcf_contracts_in_gld_mode(self):
|
|
"""Test GC=F contracts converted to GLD shares in GLD mode."""
|
|
pos = create_position("GC=F", Decimal("1"), "contracts", Decimal("215000"))
|
|
qty, unit = position_to_display_units(pos, "GLD")
|
|
assert unit == "shares"
|
|
# 100 oz should be ~1092 shares
|
|
assert Decimal("1000") < qty < Decimal("1100")
|
|
|
|
|
|
class TestCollateralToDisplayUnits:
|
|
"""Test collateral conversion to display units."""
|
|
|
|
def test_collateral_in_gld_mode(self):
|
|
"""Test collateral converted to GLD shares."""
|
|
qty, unit = collateral_to_display_units(1000.0, "GLD")
|
|
assert unit == "shares"
|
|
assert qty > 10000 # Should be ~10920 shares
|
|
|
|
def test_collateral_in_xau_oz_mode(self):
|
|
"""Test collateral stays in ounces."""
|
|
qty, unit = collateral_to_display_units(1000.0, "XAU_OZ")
|
|
assert unit == "oz"
|
|
assert qty == 1000.0
|
|
|
|
def test_collateral_in_xau_g_mode(self):
|
|
"""Test collateral converted to grams."""
|
|
qty, unit = collateral_to_display_units(1000.0, "XAU_G")
|
|
assert unit == "g"
|
|
assert qty == pytest.approx(31103.5, rel=0.01)
|
|
|
|
def test_collateral_in_gcf_mode(self):
|
|
"""Test collateral converted to contracts."""
|
|
qty, unit = collateral_to_display_units(1000.0, "GCF")
|
|
assert unit == "contracts"
|
|
assert qty == pytest.approx(10.0, rel=0.01)
|
|
|
|
|
|
class TestPortfolioConfigDisplayMode:
|
|
"""Test PortfolioConfig display_mode field."""
|
|
|
|
def test_default_display_mode(self):
|
|
"""Test default display mode is GLD."""
|
|
from app.models.portfolio import PortfolioConfig
|
|
|
|
config = PortfolioConfig()
|
|
assert config.display_mode == "GLD"
|
|
|
|
def test_custom_display_mode(self):
|
|
"""Test custom display mode."""
|
|
from app.models.portfolio import PortfolioConfig
|
|
|
|
config = PortfolioConfig(display_mode="XAU_OZ")
|
|
assert config.display_mode == "XAU_OZ"
|
|
|
|
def test_display_mode_in_to_dict(self):
|
|
"""Test display_mode is included in to_dict."""
|
|
from app.models.portfolio import PortfolioConfig
|
|
|
|
config = PortfolioConfig(display_mode="XAU_G")
|
|
config_dict = config.to_dict()
|
|
assert "display_mode" in config_dict
|
|
assert config_dict["display_mode"] == "XAU_G"
|
|
|
|
def test_display_mode_in_from_dict(self):
|
|
"""Test display_mode is restored from dict."""
|
|
from app.models.portfolio import PortfolioConfig
|
|
|
|
config_dict = {
|
|
"gold_value": 215000.0,
|
|
"entry_price": 2150.0,
|
|
"gold_ounces": 100.0,
|
|
"display_mode": "GCF",
|
|
}
|
|
config = PortfolioConfig.from_dict(config_dict)
|
|
assert config.display_mode == "GCF"
|