257 lines
9.0 KiB
Python
257 lines
9.0 KiB
Python
from __future__ import annotations
|
|
|
|
|
|
def _login(client, username: str) -> None:
|
|
client.post('/api/auth/register', json={'username': username, 'password': 'secret12'})
|
|
|
|
|
|
def test_create_room_and_join_room(client):
|
|
_login(client, 'alice_room')
|
|
create_resp = client.post('/api/rooms/create', json={})
|
|
assert create_resp.status_code == 200
|
|
create_data = create_resp.get_json()
|
|
assert create_data['ok'] is True
|
|
|
|
room_id = create_data['room_id']
|
|
host_player_id = create_data['player_id']
|
|
assert len(room_id) == 6
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'bob_room')
|
|
join_resp = client.post(
|
|
'/api/rooms/join',
|
|
json={'room_id': room_id},
|
|
)
|
|
assert join_resp.status_code == 200
|
|
join_data = join_resp.get_json()
|
|
assert join_data['ok'] is True
|
|
assert join_data['player_id'] != host_player_id
|
|
|
|
|
|
def test_join_room_reconnect_with_cached_player_id(client):
|
|
_login(client, 'host_reconnect')
|
|
create_data = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = create_data['room_id']
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'member_reconnect')
|
|
join_data = client.post(
|
|
'/api/rooms/join',
|
|
json={'room_id': room_id},
|
|
).get_json()
|
|
|
|
reconnect = client.post(
|
|
'/api/rooms/join',
|
|
json={'room_id': room_id, 'player_id': join_data['player_id']},
|
|
)
|
|
assert reconnect.status_code == 200
|
|
reconnect_data = reconnect.get_json()
|
|
assert reconnect_data['player_id'] == join_data['player_id']
|
|
assert reconnect_data['player_name'] == 'member_reconnect'
|
|
|
|
|
|
def test_join_room_missing_room(client):
|
|
_login(client, 'missing_room_user')
|
|
resp = client.post(
|
|
'/api/rooms/join',
|
|
json={'room_id': 'XXXXXX'},
|
|
)
|
|
assert resp.status_code == 400
|
|
data = resp.get_json()
|
|
assert data['ok'] is False
|
|
assert '房间不存在' in data['error']
|
|
|
|
|
|
def test_host_can_delete_room(client):
|
|
_login(client, 'host_delete')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
host_player_id = created['player_id']
|
|
|
|
deleted = client.delete(f'/api/rooms/{room_id}', json={'player_id': host_player_id})
|
|
assert deleted.status_code == 200
|
|
assert deleted.get_json()['ok'] is True
|
|
|
|
snapshot = client.get(f'/api/rooms/{room_id}/snapshot')
|
|
assert snapshot.status_code == 404
|
|
|
|
|
|
def test_non_host_cannot_delete_room(client):
|
|
_login(client, 'host_non_delete')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'guest_non_delete')
|
|
guest = client.post('/api/rooms/join', json={'room_id': room_id}).get_json()
|
|
|
|
denied = client.delete(f'/api/rooms/{room_id}', json={'player_id': guest['player_id']})
|
|
assert denied.status_code == 400
|
|
assert '只有房主可以删除房间' in denied.get_json()['error']
|
|
|
|
|
|
def test_lobby_join_requires_login_and_running_allows_spectator(client, app_instance):
|
|
_login(client, 'host_invite')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
host_id = created['player_id']
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
denied = client.post('/api/rooms/join', json={'room_id': room_id})
|
|
assert denied.status_code == 401
|
|
|
|
_login(client, 'mate_invite')
|
|
mate = client.post('/api/rooms/join', json={'room_id': room_id}).get_json()
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'host_invite')
|
|
app, _ = app_instance
|
|
app.extensions['room_manager'].set_ready(room_id, mate['player_id'], True)
|
|
app.extensions['room_manager'].start_game(room_id, host_id)
|
|
client.post('/api/auth/logout', json={})
|
|
|
|
spectate = client.post('/api/rooms/join', json={'room_id': room_id})
|
|
payload = spectate.get_json()
|
|
assert spectate.status_code == 200
|
|
assert payload['ok'] is True
|
|
assert payload['is_spectator'] is True
|
|
|
|
|
|
def test_running_room_supports_spectator_page_without_login(client, app_instance):
|
|
_login(client, 'spectator_host')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
host_id = created['player_id']
|
|
app, _ = app_instance
|
|
app.extensions['room_manager'].start_game(room_id, host_id)
|
|
client.post('/api/auth/logout', json={})
|
|
|
|
page = client.get(f'/room/{room_id}?spectator=1')
|
|
assert page.status_code == 200
|
|
html = page.get_data(as_text=True)
|
|
assert 'data-spectator="1"' in html
|
|
|
|
|
|
def test_my_rooms_api_keeps_ended_status(client, app_instance):
|
|
_login(client, 'ended_room_owner')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
host_id = created['player_id']
|
|
|
|
app, _ = app_instance
|
|
manager = app.extensions['room_manager']
|
|
persistence = app.extensions['persistence']
|
|
manager.start_game(room_id, host_id)
|
|
|
|
room = persistence.get_room(room_id)
|
|
state = dict(room['game_state'])
|
|
state['game_phase'] = 'ended'
|
|
state['ending_state'] = 'custom_end'
|
|
state.setdefault('global_flags', {})
|
|
state['global_flags']['ending_summary'] = '测试结局'
|
|
persistence.update_room_state(room_id, 'ended', state)
|
|
|
|
rooms_resp = client.get('/api/me/rooms')
|
|
payload = rooms_resp.get_json()
|
|
assert rooms_resp.status_code == 200
|
|
assert payload['ok'] is True
|
|
row = next((item for item in payload['rooms'] if item['room_id'] == room_id), None)
|
|
assert row is not None
|
|
assert row['status'] == 'ended'
|
|
|
|
|
|
def test_host_can_set_room_public_and_public_list_can_see_it(client):
|
|
_login(client, 'host_public_1')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
host_id = created['player_id']
|
|
|
|
toggled = client.patch(
|
|
f'/api/rooms/{room_id}/visibility',
|
|
json={'player_id': host_id, 'is_public': True},
|
|
)
|
|
assert toggled.status_code == 200
|
|
data = toggled.get_json()
|
|
assert data['ok'] is True
|
|
assert data['is_public'] is True
|
|
assert data['snapshot']['is_public'] is True
|
|
|
|
public_resp = client.get('/api/rooms/public?limit=20')
|
|
assert public_resp.status_code == 200
|
|
public_data = public_resp.get_json()
|
|
assert public_data['ok'] is True
|
|
row = next((item for item in public_data['rooms'] if item['room_id'] == room_id), None)
|
|
assert row is not None
|
|
assert row['status'] == 'lobby'
|
|
|
|
|
|
def test_non_host_cannot_set_room_public(client):
|
|
_login(client, 'host_public_2')
|
|
created = client.post('/api/rooms/create', json={}).get_json()
|
|
room_id = created['room_id']
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'guest_public_2')
|
|
guest = client.post('/api/rooms/join', json={'room_id': room_id}).get_json()
|
|
|
|
denied = client.patch(
|
|
f'/api/rooms/{room_id}/visibility',
|
|
json={'player_id': guest['player_id'], 'is_public': True},
|
|
)
|
|
assert denied.status_code == 400
|
|
payload = denied.get_json()
|
|
assert payload['ok'] is False
|
|
assert '只有房主可以设置房间公开状态' in payload['error']
|
|
|
|
|
|
def test_leaderboard_api_returns_ranked_players(client, app_instance):
|
|
app, _ = app_instance
|
|
manager = app.extensions['room_manager']
|
|
persistence = app.extensions['persistence']
|
|
|
|
_login(client, 'leader_alpha')
|
|
alpha_1 = client.post('/api/rooms/create', json={}).get_json()
|
|
manager.start_game(alpha_1['room_id'], alpha_1['player_id'])
|
|
room = persistence.get_room(alpha_1['room_id'])
|
|
state = dict(room['game_state'])
|
|
state['game_phase'] = 'ended'
|
|
state['ending_state'] = 'escaped'
|
|
state['round_no'] = 6
|
|
persistence.update_room_state(alpha_1['room_id'], 'ended', state)
|
|
|
|
alpha_2 = client.post('/api/rooms/create', json={}).get_json()
|
|
manager.start_game(alpha_2['room_id'], alpha_2['player_id'])
|
|
room = persistence.get_room(alpha_2['room_id'])
|
|
state = dict(room['game_state'])
|
|
state['game_phase'] = 'ended'
|
|
state['ending_state'] = 'victory'
|
|
state['round_no'] = 8
|
|
persistence.update_room_state(alpha_2['room_id'], 'ended', state)
|
|
|
|
client.post('/api/auth/logout', json={})
|
|
_login(client, 'leader_bravo')
|
|
bravo_1 = client.post('/api/rooms/create', json={}).get_json()
|
|
manager.start_game(bravo_1['room_id'], bravo_1['player_id'])
|
|
room = persistence.get_room(bravo_1['room_id'])
|
|
state = dict(room['game_state'])
|
|
state['game_phase'] = 'ended'
|
|
state['ending_state'] = 'trapped'
|
|
state['round_no'] = 9
|
|
persistence.update_room_state(bravo_1['room_id'], 'ended', state)
|
|
|
|
leaderboard_resp = client.get('/api/leaderboard?limit=10')
|
|
assert leaderboard_resp.status_code == 200
|
|
payload = leaderboard_resp.get_json()
|
|
assert payload['ok'] is True
|
|
|
|
rows = payload['leaderboard']
|
|
assert len(rows) >= 2
|
|
assert rows[0]['username'] == 'leader_alpha'
|
|
assert rows[0]['wins'] == 2
|
|
assert rows[0]['played_games'] == 2
|
|
assert rows[0]['rank'] == 1
|
|
|
|
bravo = next((row for row in rows if row['username'] == 'leader_bravo'), None)
|
|
assert bravo is not None
|
|
assert bravo['wins'] == 0
|
|
assert bravo['played_games'] == 1
|