relo-calculator / tests /test_regression.py
sabilmakbar's picture
add landing page; move relocation calculator to /relo and add tool nav
b56f75b
Raw
History Blame Contribute Delete
3.54 kB
"""Regression tests β€” each pins a specific bug we fixed, so it can't return.
Reference the symptom in the test name/docstring so a future failure is
self-explanatory.
"""
import pytest
from fastapi.testclient import TestClient
from app.main import app
from app.model import calculate_stats
client = TestClient(app)
COL = {"valuePct": 134.5, "direction": "higher"}
RENT = {"valuePct": 409.4, "direction": "higher"}
async def fake_diffs(country1, city1, country2, city2):
return {"city_from": city1, "city_to": city2,
"col_excl_rent": COL, "rent": RENT}
async def fake_fx(from_currency, to_currency):
return {"pair": f"{from_currency}/{to_currency}", "source": "Yahoo Finance",
"latest": 0.30, "ema_30": 0.30, "ema_90": 0.30, "ema_180": 0.30,
"forecast": 0.30, "trend": "flat", "spot_only": False, "scale": 1,
"band_low": 0.30, "band_high": 0.30, "days": 200}
@pytest.fixture
def patched(monkeypatch):
monkeypatch.setattr("app.main.get_percentage_diff", fake_diffs)
monkeypatch.setattr("app.main.fetch_fx_ema", fake_fx)
def test_currency_scale_bug_no_nonsensical_negative_savings():
"""Was: destination costs computed on home-currency scale while net_new was
in destination currency β†’ wildly negative savings. Now FX-scaled."""
m = calculate_stats(16000, 24000, COL, RENT, fx_rate=0.30, w_rent=0.2, w_non_rent=0.6)
assert m["rent_new"] == pytest.approx(0.2 * (16000 * 0.30) * (1 + 4.094))
assert m["savings_new"] > 0 # not a huge negative number
def test_bare_except_no_longer_swallows_errors(patched, monkeypatch):
"""Was: a single bare `except` hid all failures. Now ValueErrors surface
as user-facing messages."""
r = client.post("/compare", data={
"country1": "Malaysia", "city1": "Kuala Lumpur",
"country2": "Singapore", "city2": "Singapore",
"net_home": "16000", # neither net_new nor increment_pct
})
assert "Provide either a new net salary" in r.text
def test_thousand_separated_salary_input_is_accepted(patched):
"""Was: switching salary inputs to formatted text broke float parsing.
Now commas are stripped server-side."""
r = client.post("/compare", data={
"country1": "Malaysia", "city1": "Kuala Lumpur",
"country2": "Malaysia", "city2": "Penang",
"net_home": "16,000", "net_new": "18,500",
})
assert r.status_code == 200
assert "Monthly savings estimate" in r.text
def test_get_compare_redirects_not_405():
"""Was: GET /compare returned 405. Now redirects home."""
r = client.get("/compare", follow_redirects=False)
assert r.status_code == 303
assert r.headers["location"] == "/relo"
def test_multiword_names_title_cased_not_lowercased(patched):
"""Was: .capitalize() turned 'Kuala Lumpur' into 'Kuala lumpur'. Now .title()."""
r = client.post("/compare", data={
"country1": "Malaysia", "city1": "kuala lumpur",
"country2": "Malaysia", "city2": "george town",
"net_home": "10000", "net_new": "11000",
})
assert r.status_code == 200
# city_from echoes the (title-cased) submitted city
assert "Kuala Lumpur" in r.text
assert "Kuala lumpur" not in r.text
def test_savings_pct_delta_uses_home_equivalent():
"""Was: % delta mixed currencies. Now compares home-currency equivalents."""
m = calculate_stats(10000, 10000, COL, RENT, fx_rate=1.0)
# same salary, pricier destination β†’ fewer savings β†’ negative delta
assert m["savings_pct_delta"] < 0