feat: add setup notebook and update env example for Athena
This commit is contained in:
@@ -83,11 +83,71 @@ class TestPaths:
|
||||
|
||||
def test_save_version_path(self, client):
|
||||
client.session.request.return_value = _mock_response(201, {"version_number": 1})
|
||||
client.save_version("abc", note="initial")
|
||||
client.save_version("abc", note="initial", date="2026-06-10")
|
||||
url = self._last_call_url(client)
|
||||
assert url.endswith("/api/v1/tei/tools/abc/versions/")
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert body == {"note": "initial"}
|
||||
assert body == {"date": "2026-06-10", "note": "initial"}
|
||||
|
||||
def test_save_version_defaults_date_to_today(self, client):
|
||||
client.session.request.return_value = _mock_response(201, {"version_number": 1})
|
||||
client.save_version("abc", note="x")
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert body["note"] == "x"
|
||||
assert len(body["date"]) == 10 # YYYY-MM-DD
|
||||
|
||||
def test_patch_value_year_in_query(self, client):
|
||||
client.session.request.return_value = _mock_response(200, {})
|
||||
client.patch_value("abc", "fkey", year=2, value=100)
|
||||
url = self._last_call_url(client)
|
||||
assert url.endswith("/api/v1/tei/tools/abc/values/fkey/?year=2")
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert body == {"value": "100"}
|
||||
|
||||
def test_list_clients_path(self, client):
|
||||
client.session.request.return_value = _mock_response(
|
||||
200, {"results": [], "next": None}
|
||||
)
|
||||
client.list_clients(search="acme")
|
||||
assert self._last_call_url(client).endswith("/api/v1/orbit/clients/")
|
||||
assert client.session.request.call_args.kwargs["params"] == {"search": "acme"}
|
||||
|
||||
def test_list_proposals_filters_by_opportunity(self, client):
|
||||
client.session.request.return_value = _mock_response(
|
||||
200, {"results": [], "next": None}
|
||||
)
|
||||
client.list_proposals(opportunity_id=42)
|
||||
assert self._last_call_url(client).endswith("/api/v1/orbit/proposals/")
|
||||
assert client.session.request.call_args.kwargs["params"] == {
|
||||
"opportunity_id": 42
|
||||
}
|
||||
|
||||
def test_list_engagements_path(self, client):
|
||||
client.session.request.return_value = _mock_response(
|
||||
200, {"results": [], "next": None}
|
||||
)
|
||||
client.list_engagements()
|
||||
assert self._last_call_url(client).endswith(
|
||||
"/api/v1/engagement/engagements/"
|
||||
)
|
||||
|
||||
def test_create_proposal_body(self, client):
|
||||
client.session.request.return_value = _mock_response(201, {"id": 7})
|
||||
client.create_proposal("Acme TEI", opportunity_id=42)
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert body == {"name": "Acme TEI", "opportunity_id": 42, "status": "Draft"}
|
||||
|
||||
def test_reorder_fields_body(self, client):
|
||||
client.session.request.return_value = _mock_response(200, {})
|
||||
client.reorder_fields("rep", [7, 3, 9])
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert body == {
|
||||
"field_order": [
|
||||
{"id": 7, "sort_order": 1},
|
||||
{"id": 3, "sort_order": 2},
|
||||
{"id": 9, "sort_order": 3},
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
class TestErrorHandling:
|
||||
@@ -129,39 +189,52 @@ class TestPagination:
|
||||
assert [r["id"] for r in out] == [1, 2]
|
||||
|
||||
|
||||
class TestNormalizeValue:
|
||||
class TestRowsFromValue:
|
||||
"""_rows_from_value expands friendly dicts into documented wire rows."""
|
||||
|
||||
def test_year_underscore_keys(self):
|
||||
out = TEIClient._normalize_value(
|
||||
rows = TEIClient._rows_from_value(
|
||||
{"field_key": "x", "year_1": 100, "year_2": 200, "risk_adjustment": 0.1}
|
||||
)
|
||||
assert out["year_values"] == {"1": 100.0, "2": 200.0}
|
||||
assert out["risk_adjustment"] == 0.1
|
||||
assert [(r["field_key"], r["year"], r["value"]) for r in rows] == [
|
||||
("x", 1, "100.0"),
|
||||
("x", 2, "200.0"),
|
||||
]
|
||||
assert all(r["risk_adjustment"] == "0.1" for r in rows)
|
||||
|
||||
def test_year_values_dict_passthrough(self):
|
||||
out = TEIClient._normalize_value(
|
||||
{
|
||||
"field_key": "x",
|
||||
"year_values": {"1": 50, "3": 75},
|
||||
"notes": " hi ",
|
||||
}
|
||||
def test_year_values_dict(self):
|
||||
rows = TEIClient._rows_from_value(
|
||||
{"field_key": "x", "year_values": {"1": 50, "3": 75}, "notes": "hi"}
|
||||
)
|
||||
assert out["year_values"] == {"1": 50.0, "3": 75.0}
|
||||
assert out["notes"] == " hi "
|
||||
assert [(r["year"], r["value"]) for r in rows] == [(1, "50.0"), (3, "75.0")]
|
||||
# Notes land on the first year row only.
|
||||
assert rows[0]["notes"] == "hi"
|
||||
assert rows[1]["notes"] is None
|
||||
|
||||
def test_initial_carried(self):
|
||||
out = TEIClient._normalize_value(
|
||||
def test_initial_becomes_companion_row(self):
|
||||
rows = TEIClient._rows_from_value(
|
||||
{"field_key": "x", "initial": 1000, "year_1": 5}
|
||||
)
|
||||
assert out["initial"] == 1000.0
|
||||
companion = [r for r in rows if r["field_key"] == "x_initial"]
|
||||
assert len(companion) == 1
|
||||
assert companion[0]["year"] is None
|
||||
assert companion[0]["value"] == "1000.0"
|
||||
|
||||
def test_scalar_value(self):
|
||||
out = TEIClient._normalize_value({"field_key": "rate", "value": 0.10})
|
||||
assert out["value"] == 0.10
|
||||
assert "year_values" not in out
|
||||
rows = TEIClient._rows_from_value({"field_key": "rate", "value": 0.10})
|
||||
assert rows == [
|
||||
{
|
||||
"field_key": "rate",
|
||||
"year": None,
|
||||
"value": "0.1",
|
||||
"risk_adjustment": None,
|
||||
"notes": None,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class TestUpdateValuesPayload:
|
||||
def test_wraps_in_envelope(self, client):
|
||||
def test_flat_rows_in_envelope(self, client):
|
||||
client.session.request.return_value = _mock_response(200, {})
|
||||
client.update_values(
|
||||
"abc",
|
||||
@@ -169,6 +242,52 @@ class TestUpdateValuesPayload:
|
||||
)
|
||||
body = client.session.request.call_args.kwargs["json"]
|
||||
assert "values" in body
|
||||
assert len(body["values"]) == 2
|
||||
assert body["values"][0]["field_key"] == "x"
|
||||
assert body["values"][0]["year_values"] == {"1": 100.0}
|
||||
assert len(body["values"]) == 2 # one row per field/year
|
||||
assert body["values"][0] == {
|
||||
"field_key": "x",
|
||||
"year": 1,
|
||||
"value": "100.0",
|
||||
"risk_adjustment": None,
|
||||
"notes": None,
|
||||
}
|
||||
|
||||
|
||||
class TestGetValuesFriendlyShape:
|
||||
def test_documented_years_shape_is_flattened(self, client):
|
||||
client.session.request.return_value = _mock_response(
|
||||
200,
|
||||
{
|
||||
"tool_id": "abc",
|
||||
"values": [
|
||||
{
|
||||
"field_key": "ben",
|
||||
"table": "benefits",
|
||||
"is_annual": True,
|
||||
"risk_adjustment": "0.15",
|
||||
"years": {
|
||||
"1": {"value": "100.00", "risk_adjustment": None, "notes": ""},
|
||||
"2": {"value": "200.00", "risk_adjustment": None, "notes": ""},
|
||||
},
|
||||
},
|
||||
{
|
||||
"field_key": "cost",
|
||||
"table": "costs",
|
||||
"is_annual": True,
|
||||
"years": {"1": {"value": "10.00"}},
|
||||
},
|
||||
{
|
||||
"field_key": "cost_initial",
|
||||
"table": "costs",
|
||||
"is_annual": False,
|
||||
"value": "500.00",
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
rows = client.get_values("abc")
|
||||
by_key = {r["field_key"]: r for r in rows}
|
||||
assert by_key["ben"]["year_values"] == {"1": 100.0, "2": 200.0}
|
||||
assert by_key["ben"]["risk_adjustment"] == 0.15
|
||||
# companion *_initial folded into parent, not standalone
|
||||
assert "cost_initial" not in by_key
|
||||
assert by_key["cost"]["initial"] == 500.0
|
||||
|
||||
Reference in New Issue
Block a user