Fix combined search filter semantics across player season joins
This commit is contained in:
@ -154,3 +154,45 @@ def test_player_detail_api_includes_origin_fields(client):
|
||||
payload = response.json()
|
||||
assert payload["origin_competition"] == competition.name
|
||||
assert payload["origin_team"] == team.name
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_api_combined_filters_respect_same_player_season_context(client):
|
||||
nationality = Nationality.objects.create(name="Poland", iso2_code="PL", iso3_code="POL")
|
||||
competition = Competition.objects.create(
|
||||
name="PLK",
|
||||
slug="plk",
|
||||
competition_type=Competition.CompetitionType.LEAGUE,
|
||||
gender=Competition.Gender.MEN,
|
||||
country=nationality,
|
||||
)
|
||||
season = Season.objects.create(label="2024-2025", start_date=date(2024, 9, 1), end_date=date(2025, 6, 30))
|
||||
team_a = Team.objects.create(name="Warsaw", slug="warsaw", country=nationality)
|
||||
team_b = Team.objects.create(name="Gdansk", slug="gdansk", country=nationality)
|
||||
|
||||
player = Player.objects.create(first_name="Piotr", last_name="Filter", full_name="Piotr Filter", nationality=nationality)
|
||||
ps_a = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=team_a,
|
||||
competition=competition,
|
||||
games_played=10,
|
||||
minutes_played=200,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(player_season=ps_a, points=7, rebounds=2, assists=3, steals=1, blocks=0, turnovers=1)
|
||||
ps_b = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=team_b,
|
||||
competition=competition,
|
||||
games_played=10,
|
||||
minutes_played=300,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(player_season=ps_b, points=21, rebounds=4, assists=5, steals=1, blocks=0, turnovers=2)
|
||||
|
||||
response = client.get(
|
||||
reverse("api:players"),
|
||||
data={"team": team_a.id, "season": season.id, "competition": competition.id, "points_per_game_min": "20"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["count"] == 0
|
||||
|
||||
@ -186,3 +186,149 @@ def test_player_search_results_include_favorite_ids(client):
|
||||
response = client.get(reverse("players:index"))
|
||||
assert response.status_code == 200
|
||||
assert player.id in response.context["favorite_player_ids"]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_combined_reverse_join_filters_do_not_match_across_different_player_seasons(client):
|
||||
nationality = Nationality.objects.create(name="Lithuania", iso2_code="LT", iso3_code="LTU")
|
||||
position = Position.objects.create(code="SG", name="Shooting Guard")
|
||||
role = Role.objects.create(code="scorer", name="Scorer")
|
||||
competition = Competition.objects.create(
|
||||
name="LKL",
|
||||
slug="lkl",
|
||||
competition_type=Competition.CompetitionType.LEAGUE,
|
||||
gender=Competition.Gender.MEN,
|
||||
country=nationality,
|
||||
)
|
||||
season = Season.objects.create(label="2025-2026", start_date=date(2025, 9, 1), end_date=date(2026, 6, 30))
|
||||
target_team = Team.objects.create(name="Kaunas", slug="kaunas", country=nationality)
|
||||
other_team = Team.objects.create(name="Vilnius", slug="vilnius", country=nationality)
|
||||
|
||||
player = Player.objects.create(
|
||||
first_name="Jonas",
|
||||
last_name="Scope",
|
||||
full_name="Jonas Scope",
|
||||
birth_date=date(2001, 1, 1),
|
||||
nationality=nationality,
|
||||
nominal_position=position,
|
||||
inferred_role=role,
|
||||
)
|
||||
|
||||
# Matching team/season row but low scoring.
|
||||
ps_target = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=target_team,
|
||||
competition=competition,
|
||||
games_played=20,
|
||||
minutes_played=400,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(
|
||||
player_season=ps_target,
|
||||
points=8.0,
|
||||
rebounds=3.0,
|
||||
assists=2.0,
|
||||
steals=1.0,
|
||||
blocks=0.2,
|
||||
turnovers=1.5,
|
||||
)
|
||||
|
||||
# High-scoring row but different team; should not satisfy combined filter.
|
||||
ps_other = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=other_team,
|
||||
competition=competition,
|
||||
games_played=20,
|
||||
minutes_played=400,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(
|
||||
player_season=ps_other,
|
||||
points=22.0,
|
||||
rebounds=4.0,
|
||||
assists=3.0,
|
||||
steals=1.2,
|
||||
blocks=0.3,
|
||||
turnovers=2.0,
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
reverse("players:index"),
|
||||
data={
|
||||
"team": target_team.id,
|
||||
"season": season.id,
|
||||
"competition": competition.id,
|
||||
"points_per_game_min": "20",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert list(response.context["players"]) == []
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_displayed_metrics_are_scoped_to_filtered_context(client):
|
||||
nationality = Nationality.objects.create(name="Turkey", iso2_code="TR", iso3_code="TUR")
|
||||
position = Position.objects.create(code="PG", name="Point Guard")
|
||||
role = Role.objects.create(code="playmaker", name="Playmaker")
|
||||
competition = Competition.objects.create(
|
||||
name="BSL",
|
||||
slug="bsl",
|
||||
competition_type=Competition.CompetitionType.LEAGUE,
|
||||
gender=Competition.Gender.MEN,
|
||||
country=nationality,
|
||||
)
|
||||
season = Season.objects.create(label="2025-2026", start_date=date(2025, 9, 1), end_date=date(2026, 6, 30))
|
||||
target_team = Team.objects.create(name="Ankara", slug="ankara", country=nationality)
|
||||
other_team = Team.objects.create(name="Izmir", slug="izmir", country=nationality)
|
||||
|
||||
player = Player.objects.create(
|
||||
first_name="Can",
|
||||
last_name="Context",
|
||||
full_name="Can Context",
|
||||
birth_date=date(2000, 2, 2),
|
||||
nationality=nationality,
|
||||
nominal_position=position,
|
||||
inferred_role=role,
|
||||
)
|
||||
|
||||
ps_target = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=target_team,
|
||||
competition=competition,
|
||||
games_played=10,
|
||||
minutes_played=250,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(
|
||||
player_season=ps_target,
|
||||
points=9.0,
|
||||
rebounds=2.0,
|
||||
assists=4.0,
|
||||
steals=1.0,
|
||||
blocks=0.1,
|
||||
turnovers=2.0,
|
||||
)
|
||||
|
||||
ps_other = PlayerSeason.objects.create(
|
||||
player=player,
|
||||
season=season,
|
||||
team=other_team,
|
||||
competition=competition,
|
||||
games_played=12,
|
||||
minutes_played=420,
|
||||
)
|
||||
PlayerSeasonStats.objects.create(
|
||||
player_season=ps_other,
|
||||
points=24.0,
|
||||
rebounds=5.0,
|
||||
assists=7.0,
|
||||
steals=1.5,
|
||||
blocks=0.2,
|
||||
turnovers=3.0,
|
||||
)
|
||||
|
||||
response = client.get(reverse("players:index"), data={"team": target_team.id, "season": season.id})
|
||||
assert response.status_code == 200
|
||||
row = list(response.context["players"])[0]
|
||||
assert float(row.ppg_value) == pytest.approx(9.0)
|
||||
assert float(row.mpg_value) == pytest.approx(25.0)
|
||||
|
||||
Reference in New Issue
Block a user