From 18a809d6e18182956e699d775acbc3544695bbe9 Mon Sep 17 00:00:00 2001 From: kerry Date: Tue, 22 Sep 2026 21:33:44 +0000 Subject: [PATCH] test(integration): explicit null budget_duration on /team/new is not replaced by default_team_params (Pylon #7536) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- tests/integration/contracts.json | 3 + .../test_team_budget_duration_defaults.py | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 tests/integration/management/test_team_budget_duration_defaults.py diff --git a/tests/integration/contracts.json b/tests/integration/contracts.json index 9f1619a2202..c35af2ea6a6 100644 --- a/tests/integration/contracts.json +++ b/tests/integration/contracts.json @@ -30,6 +30,9 @@ ] }, "tests": { + "tests/integration/management/test_team_budget_duration_defaults.py::test_team_new_explicit_null_budget_duration_is_not_replaced_by_default": [ + "mgmt.team.new.explicit_null_budget_duration_overrides_default" + ], "tests/integration/management/test_key_updates.py::test_update_preserves_independent_fields_and_serving": [ "mgmt.key.update.preserves_independent_fields" ], diff --git a/tests/integration/management/test_team_budget_duration_defaults.py b/tests/integration/management/test_team_budget_duration_defaults.py new file mode 100644 index 00000000000..9fadf7c5b5f --- /dev/null +++ b/tests/integration/management/test_team_budget_duration_defaults.py @@ -0,0 +1,64 @@ +import uuid +from collections.abc import Iterator +from contextlib import contextmanager +from typing import Final + +import pytest +from pydantic import JsonValue + +from tests.integration._support.client import Gateway, string_value +from tests.integration._support.database import read_rows + + +@contextmanager +def _default_team_budget_duration(gateway: Gateway, duration: str) -> Iterator[None]: + configured: Final = gateway.request("PATCH", "/update/default_team_settings", {"budget_duration": duration}) + assert configured.status_code == 200, configured.text + try: + yield + finally: + cleared: Final = gateway.request("PATCH", "/update/default_team_settings", {}) + assert cleared.status_code == 200, cleared.text + + +def _budget_row(team_id: str) -> dict[str, JsonValue]: + rows: Final = read_rows( + 'SELECT max_budget, budget_duration, budget_reset_at::text FROM "LiteLLM_TeamTable" WHERE team_id = %s', + (team_id,), + ) + assert len(rows) == 1, rows + return rows[0] + + +@pytest.mark.covers("mgmt.team.new.explicit_null_budget_duration_overrides_default") +def test_team_new_explicit_null_budget_duration_is_not_replaced_by_default(gateway: Gateway) -> None: + with gateway.scenario() as scenario, _default_team_budget_duration(gateway, "30d"): + never_resetting: Final = gateway.request( + "POST", + "/team/new", + {"team_alias": f"integration-{uuid.uuid4().hex}", "max_budget": 500, "budget_duration": None}, + ) + assert never_resetting.status_code == 200, never_resetting.text + never_resetting_id: Final = string_value(never_resetting.json()["team_id"]) + scenario.cleanups.callback(scenario.delete_team, never_resetting_id) + assert never_resetting.json()["max_budget"] == 500.0, never_resetting.text + assert never_resetting.json()["budget_duration"] is None, never_resetting.text + assert never_resetting.json()["budget_reset_at"] is None, never_resetting.text + assert _budget_row(never_resetting_id) == { + "max_budget": 500.0, + "budget_duration": None, + "budget_reset_at": None, + } + + inheriting: Final = gateway.request( + "POST", "/team/new", {"team_alias": f"integration-{uuid.uuid4().hex}", "max_budget": 500} + ) + assert inheriting.status_code == 200, inheriting.text + inheriting_id: Final = string_value(inheriting.json()["team_id"]) + scenario.cleanups.callback(scenario.delete_team, inheriting_id) + assert inheriting.json()["budget_duration"] == "30d", inheriting.text + assert inheriting.json()["budget_reset_at"] is not None, inheriting.text + inheriting_row: Final = _budget_row(inheriting_id) + assert inheriting_row["max_budget"] == 500.0, inheriting_row + assert inheriting_row["budget_duration"] == "30d", inheriting_row + assert inheriting_row["budget_reset_at"] is not None, inheriting_row