249 lines
8.9 KiB
Python
249 lines
8.9 KiB
Python
"""Player-specific evaluation views (the "By player" toggle and its page).
|
|
|
|
These pages regroup the flat evaluation table by player: one row per player in
|
|
the table view, and a dedicated page per player with left/right navigation and
|
|
per-criterion averages. Visibility follows the viewer's role — managers and
|
|
coaches see staff-authored evaluations inside their own tryouts.
|
|
"""
|
|
|
|
from datetime import date
|
|
|
|
import pytest
|
|
|
|
from app.extensions import db
|
|
from app.models import Evaluation, Tryout
|
|
|
|
|
|
@pytest.fixture
|
|
def staff_setup(app, as_role, make_user):
|
|
"""A coach who manages one tryout, plus staff, a player, and a foreign tryout."""
|
|
coach_id = as_role('coach', username='viewer_coach')
|
|
manager_id = make_user('manager', username='other_manager')
|
|
admin_id = make_user('admin', username='the_admin')
|
|
player_id = make_user('player', username='the_player')
|
|
outsider_id = make_user('coach', username='outsider_coach')
|
|
|
|
with app.app_context():
|
|
tryout = Tryout(
|
|
title='Spring',
|
|
game='Valorant',
|
|
date=date(2030, 4, 1),
|
|
created_by=coach_id,
|
|
coach_id=coach_id,
|
|
)
|
|
db.session.add(tryout)
|
|
db.session.flush()
|
|
|
|
other_tryout = Tryout(
|
|
title='Other',
|
|
game='Valorant',
|
|
date=date(2030, 5, 1),
|
|
created_by=outsider_id,
|
|
)
|
|
db.session.add(other_tryout)
|
|
db.session.commit()
|
|
|
|
return {
|
|
'coach_id': coach_id,
|
|
'manager_id': manager_id,
|
|
'admin_id': admin_id,
|
|
'player_id': player_id,
|
|
'tryout_id': tryout.id,
|
|
'other_tryout_id': other_tryout.id,
|
|
}
|
|
|
|
|
|
class TestVisibility:
|
|
def test_coach_sees_staff_evaluations_only_in_their_tryout(self, app, client, staff_setup):
|
|
with app.app_context():
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=staff_setup['tryout_id'],
|
|
player_id=staff_setup['player_id'],
|
|
evaluator_id=staff_setup['manager_id'],
|
|
overall_score=7,
|
|
comments='manager in own tryout',
|
|
)
|
|
)
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=staff_setup['tryout_id'],
|
|
player_id=staff_setup['player_id'],
|
|
evaluator_id=staff_setup['admin_id'],
|
|
overall_score=5,
|
|
comments='admin authored',
|
|
)
|
|
)
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=staff_setup['other_tryout_id'],
|
|
player_id=staff_setup['player_id'],
|
|
evaluator_id=staff_setup['manager_id'],
|
|
overall_score=9,
|
|
comments='manager other tryout',
|
|
)
|
|
)
|
|
db.session.commit()
|
|
|
|
body = client.get(f"/evaluations/player/{staff_setup['player_id']}").get_data(as_text=True)
|
|
|
|
assert 'manager in own tryout' in body
|
|
assert 'admin authored' not in body
|
|
assert 'manager other tryout' not in body
|
|
|
|
def test_admin_sees_every_evaluation(self, app, client, as_role, make_user):
|
|
admin_id = as_role('admin', username='boss')
|
|
coach_id = make_user('coach', username='some_coach')
|
|
player_id = make_user('player', username='star')
|
|
|
|
with app.app_context():
|
|
tryout = Tryout(
|
|
title='T',
|
|
game='Valorant',
|
|
date=date(2030, 1, 1),
|
|
created_by=admin_id,
|
|
)
|
|
db.session.add(tryout)
|
|
db.session.flush()
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=tryout.id,
|
|
player_id=player_id,
|
|
evaluator_id=coach_id,
|
|
overall_score=6,
|
|
comments='coach comment',
|
|
)
|
|
)
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=tryout.id,
|
|
player_id=player_id,
|
|
evaluator_id=admin_id,
|
|
overall_score=4,
|
|
comments='admin comment',
|
|
)
|
|
)
|
|
db.session.commit()
|
|
|
|
body = client.get(f'/evaluations/player/{player_id}').get_data(as_text=True)
|
|
|
|
assert 'coach comment' in body
|
|
assert 'admin comment' in body
|
|
|
|
def test_a_player_cannot_open_the_player_page(self, client, as_role):
|
|
player_id = as_role('player')
|
|
response = client.get(f'/evaluations/player/{player_id}', follow_redirects=False)
|
|
assert response.status_code in (301, 302)
|
|
|
|
|
|
class TestAggregates:
|
|
def test_combined_and_per_criterion_averages(self, app, client, as_role, make_user):
|
|
coach_id = as_role('coach', username='agg_coach')
|
|
coach2_id = make_user('coach', username='agg_coach2')
|
|
player_id = make_user('player', username='agg_player')
|
|
|
|
with app.app_context():
|
|
tryout = Tryout(
|
|
title='Agg',
|
|
game='Valorant',
|
|
date=date(2030, 1, 1),
|
|
created_by=coach_id,
|
|
coach_id=coach_id,
|
|
)
|
|
db.session.add(tryout)
|
|
db.session.flush()
|
|
first = Evaluation(tryout_id=tryout.id, player_id=player_id, evaluator_id=coach_id)
|
|
first.apply_scores({'mecanics_score': 8, 'mental_score': 6})
|
|
second = Evaluation(tryout_id=tryout.id, player_id=player_id, evaluator_id=coach2_id)
|
|
second.apply_scores({'mecanics_score': 4, 'mental_score': 8})
|
|
db.session.add_all([first, second])
|
|
db.session.commit()
|
|
|
|
body = client.get(f'/evaluations/player/{player_id}').get_data(as_text=True)
|
|
|
|
# overall: (7 + 6) / 2 = 6.5; mecanics: 6.0; mental: 7.0.
|
|
assert '6.5' in body
|
|
assert '6.0' in body
|
|
assert '7.0' in body
|
|
|
|
|
|
class TestNavigation:
|
|
def test_players_are_ordered_best_first_with_arrows(self, app, client, as_role, make_user):
|
|
coach_id = as_role('coach', username='order_coach')
|
|
high = make_user('player', username='zzz_high')
|
|
mid = make_user('player', username='aaa_mid')
|
|
low = make_user('player', username='mmm_low')
|
|
|
|
with app.app_context():
|
|
tryout = Tryout(
|
|
title='Order',
|
|
game='Valorant',
|
|
date=date(2030, 1, 1),
|
|
created_by=coach_id,
|
|
coach_id=coach_id,
|
|
)
|
|
db.session.add(tryout)
|
|
db.session.flush()
|
|
for player_id, score in [(high, 8), (mid, 5), (low, 3)]:
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=tryout.id,
|
|
player_id=player_id,
|
|
evaluator_id=coach_id,
|
|
overall_score=score,
|
|
)
|
|
)
|
|
db.session.commit()
|
|
|
|
best = client.get(f'/evaluations/player/{high}').get_data(as_text=True)
|
|
middle = client.get(f'/evaluations/player/{mid}').get_data(as_text=True)
|
|
worst = client.get(f'/evaluations/player/{low}').get_data(as_text=True)
|
|
|
|
# Best: no previous (left arrow disabled), next is the middle player.
|
|
assert 'aria-disabled="true"' in best
|
|
assert f'/evaluations/player/{mid}' in best
|
|
assert f'/evaluations/player/{low}' not in best
|
|
|
|
# Middle: both arrows active, pointing at the neighbours.
|
|
assert f'/evaluations/player/{high}' in middle
|
|
assert f'/evaluations/player/{low}' in middle
|
|
assert 'aria-disabled="true"' not in middle
|
|
|
|
# Worst: no next (right arrow disabled), previous is the middle player.
|
|
assert 'aria-disabled="true"' in worst
|
|
assert f'/evaluations/player/{mid}' in worst
|
|
assert f'/evaluations/player/{high}' not in worst
|
|
|
|
|
|
class TestTableView:
|
|
def test_table_groups_by_player_and_keeps_the_comment(self, app, client, as_role, make_user):
|
|
coach_id = as_role('coach', username='table_coach')
|
|
player_id = make_user('player', username='table_player')
|
|
|
|
with app.app_context():
|
|
tryout = Tryout(
|
|
title='T',
|
|
game='Valorant',
|
|
date=date(2030, 1, 1),
|
|
created_by=coach_id,
|
|
coach_id=coach_id,
|
|
)
|
|
db.session.add(tryout)
|
|
db.session.flush()
|
|
db.session.add(
|
|
Evaluation(
|
|
tryout_id=tryout.id,
|
|
player_id=player_id,
|
|
evaluator_id=coach_id,
|
|
overall_score=7,
|
|
comments='a distinctive comment',
|
|
)
|
|
)
|
|
db.session.commit()
|
|
|
|
body = client.get('/evaluations').get_data(as_text=True)
|
|
|
|
assert 'table_player' in body
|
|
assert f'/evaluations/player/{player_id}' in body
|
|
assert 'a distinctive comment' in body
|