def test_game_in_the_past(client): game = mixer.blend('games.Game', datetime=datetime.utcnow() - timedelta(1)) list_url = reverse('game-list') res = client.get(list_url) assert res.status_code == status.HTTP_200_OK, 'Request should succeed' assert res.data['results'] == [], 'The game should not be in the results' res = client.get(list_url, {'all': 'true'}) assert res.data['count'] == 1, 'Unless `all` param is supplied' retrive_url = reverse('game-detail', (game.id, )) res = client.get(retrive_url) assert res.status_code == status.HTTP_200_OK, \ 'Game should be retrievable without additional parameters' mixer.blend('games.RsvpStatus', game=game, player=client.user, status=RsvpStatus.GOING) my_url = reverse('game-my') res = client.get(my_url, {'all': 'true'}) assert res.data['count'] == 1, '`all` param should work for my games'
def test_pickup_organizer_can_invite(): organizer = mixer.blend('users.User') players = mixer.cycle(6).blend('users.User') pickup_game = mixer.blend('games.Game', organizer=organizer) other_game = mixer.blend('games.Game') pickup_url = reverse('rsvp-list', (pickup_game.id, )) other_url = reverse('rsvp-list', (other_game.id, )) client = APIClient() client.force_authenticate(organizer) res = client.post(pickup_url, { 'id': players[0].id, 'rsvp': RsvpStatus.INVITED, }) assert res.status_code == status.HTTP_201_CREATED, \ 'Organizer can invite a player to his game' assert players[0].rsvps.count() == 1 assert players[0].rsvps.get().status == RsvpStatus.INVITED for i, (rsvp, _) in enumerate(RsvpStatus.RSVP_CHOICES): if rsvp == RsvpStatus.INVITED: continue res = client.post(pickup_url, {'id': players[i + 1].id, 'rsvp': rsvp}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'Organizer can not do anything other than inviting' for i, (rsvp, _) in enumerate(RsvpStatus.RSVP_CHOICES): res = client.post(other_url, {'id': players[i + 1].id, 'rsvp': rsvp}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'Organizer can not do anything in another game'
def test_email_blank_or_unique(): alice = mixer.blend('users.User', email='*****@*****.**') with pytest.raises(ValidationError): eve = mixer.blend('users.User', email='*****@*****.**') mixer.cycle(2).blend('users.User', email='')
def test_team_add_player(): player = mixer.blend('users.User') team_manager = mixer.blend('users.User') team = mixer.blend('teams.Team', managers=[team_manager]) team_url = reverse('team-detail', (team.id, )) team_players_url = reverse('team-role-list', (team.id, )) client = APIClient() client.force_authenticate(user=team_manager) res = client.post(team_players_url, { 'id': player.id, 'role': Role.INVITED, }) assert res.status_code == status.HTTP_201_CREATED, \ 'Team manager can invite players to his teams' role_id = res.data['role_id'] role_url = reverse('team-role-detail', (team.id, role_id)) client.force_authenticate(user=player) res = client.put(role_url, {'role': Role.FIELD}) assert res.status_code == status.HTTP_200_OK, \ 'Invited player can accept an invite' assert player in team.players.all(), 'Player should be in the team now'
def test_game_queryset_and_manager(): old = mixer.blend('games.Game', datetime=datetime.utcnow() - timedelta(1)) new = mixer.blend('games.Game', datetime=datetime.utcnow() + timedelta(1)) future = Game.objects.future() assert new in future, 'New game should be in the `future` query' assert old not in future, 'Old game should not be in the `future` query' assert old in Game.objects.all(), 'Old game should be in all() still'
def test_team_retrieve(): user = mixer.blend('users.User') client = APIClient() client.force_authenticate(user=user) team = mixer.blend('teams.Team') url = reverse('team-detail', (team.id, )) res = client.get(url) assert res.status_code == status.HTTP_200_OK, \ 'Should be able to retrieve team info'
def test_my_teams(): user = mixer.blend('users.User') client = APIClient() client.force_authenticate(user=user) team = mixer.blend('teams.Team', managers=[user]) url = reverse('team-managed') res = client.get(url) assert res.status_code == status.HTTP_200_OK, \ 'Should be able to retrieve managed teams' assert res.data['count'] == 1, \ 'Should be exactly one'
def test_location_model(): location = mixer.blend('games.Location') assert isinstance(eval(str(location)), Location), 'Should cover __str__' with pytest.raises(IntegrityError): "Should not allow two instances with same name + address" mixer.cycle(2).blend('games.Location', name='foo', address='bar')
def test_rsvps_annotation(): user = mixer.blend('users.User') game = mixer.blend('games.Game') RsvpStatus(player=user, game=game, status=RsvpStatus.GOING).save() RsvpStatus(player=mixer.blend('users.User'), game=game, status=RsvpStatus.GOING).save() annotated_game = Game.objects.with_rsvps(user)[0] assert annotated_game.rsvp == RsvpStatus.GOING client = APIClient() client.force_authenticate(user) res = client.get(reverse('game-list')) assert res.data['results'][0]['rsvp'] == RsvpStatus.GOING
def test_user_has_game_invites(): user = mixer.blend('users.User') rsvp = mixer.blend('games.RsvpStatus', player=user, status=RsvpStatus.INVITED) role = mixer.blend('teams.Role', player=user, status=Role.INVITED) client = APIClient() client.force_authenticate(user=user) res = client.get(reverse('current-user')) assert 'invites' in res.data, 'Sould have invites' assert res.data['invites'] == {'total': 2, 'teams': 1, 'games': 1}, \ 'Sould have two invites total, one for games and one for teams'
def test_game_create(): player1, player2 = mixer.cycle(2).blend('users.User') team_manager = mixer.blend('users.User') team = mixer.blend('teams.Team', managers=[team_manager]) player1_role = Role.objects.create( player=player1, team=team, role=Role.FIELD, ) client = APIClient() client.force_authenticate(user=team_manager) games_url = reverse('game-list') address = mixer.faker.address() location_name = ' '.join(address.split()[1:3]) res = client.post( games_url, { 'datetime': datetime.utcnow() + timedelta(1), 'location': { 'address': address, 'name': location_name, }, 'teams': [team.id], }) assert res.status_code == status.HTTP_201_CREATED, \ 'Team manager should be able to create a game for his team' game = Game.objects.get(id=res.data['id']) assert player1 in game.players.all(), \ 'Player that was in the team should be automatically invited' # Invite another player to the team team_players_url = reverse('team-role-list', (team.id, )) res = client.post(team_players_url, { 'id': player2.id, 'role': Role.INVITED, }) assert res.status_code == status.HTTP_201_CREATED, \ 'Team manager can invite players to his teams' assert player2 in game.players.all(), \ 'Player joining a team should be invited to the future team games'
def test_team_games(client): team = mixer.blend('teams.Team') mixer.cycle(5).blend('games.Game', teams=[team]) url = reverse('team-games-list', (team.id, )) res = client.get(url) assert res.status_code == status.HTTP_200_OK, 'Request should succeed' assert res.data['count'] == 5, 'User should have 5 invites'
def test_team_creator_added_as_player(): """ User that creates a team should be added to that teams as a player automatically """ user = mixer.blend('users.User') client = APIClient() client.force_authenticate(user=user) create_url = reverse('team-list') res = client.post(create_url, {'name': 'Test team'}) team = Team.objects.get(id=res.data['id']) assert user in team.players.all(), 'Creator should be a player' user2 = mixer.blend('users.User') team.managers.add(user2) assert user2 not in team.players.all(), \ 'Any extra managers are not added automatically'
def test_game_edit_permission(client): users_game = mixer.blend('games.Game', organizer=client.user) other_game = mixer.blend('games.Game') users_game_url = reverse('game-detail', (users_game.id, )) other_game_url = reverse('game-detail', (other_game.id, )) res = client.patch(users_game_url, {'description': 'test'}) assert res.status_code == status.HTTP_200_OK, \ 'User should be able to edit his game' res = client.patch(other_game_url, {'description': 'test'}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'User should not be able to edit other users games' client.user.is_superuser = True client.user.save() res = client.patch(other_game_url, {'description': 'test'}) assert res.status_code == status.HTTP_200_OK, \ 'Unless he is a superuser'
def test_team_create(): user = mixer.blend('users.User') url = reverse('team-list') client = APIClient() res = client.post(url, {'name': 'Test team'}) assert res.status_code == status.HTTP_401_UNAUTHORIZED, \ 'Unauthenticated user can not create teams' client.force_authenticate(user=user) res = client.post(url, {'name': 'Test team'}) assert res.status_code == status.HTTP_201_CREATED, \ 'User can create a team' res = client.post(url, {}) assert res.status_code == status.HTTP_400_BAD_REQUEST, \ 'Should not create a team without a name'
def test_account_delete(): user = mixer.blend('users.User') user.set_password('1234') user.save() client = APIClient() client.login(username=user.username, password='******') res = client.delete(reverse('current-user')) assert res.status_code == status.HTTP_204_NO_CONTENT, \ 'Current user should be able to delete his account' user.refresh_from_db() assert user.is_active is False, 'Must be a soft delete' res = client.get(reverse('current-user')) assert res.status_code == status.HTTP_401_UNAUTHORIZED, \ 'Should log user out'
def test_my_games(): user = mixer.blend('users.User') mixer.cycle(5).blend('games.RsvpStatus', status=RsvpStatus.GOING, player=user) client = APIClient() url = reverse('game-my') res = client.get(url) assert res.status_code == status.HTTP_401_UNAUTHORIZED, \ 'Should not be accessable when not authenticated' client.force_authenticate(user=user) res = client.get(url) assert res.status_code == status.HTTP_200_OK, 'Request should succeed' assert res.data['count'] == 5, 'User should have 5 games'
def test_game_model(): game = mixer.blend('games.Game') assert str(game) != '', 'Should cover __str__'
def test_rsvp_list(client): game = mixer.blend('games.Game') rsvps = mixer.cycle(5).blend('games.RsvpStatus', game=game) res = client.get(reverse('rsvp-list', (game.id, ))) assert res.data['count'] == 5, 'Should have 5 rsvps'
def test_user_creation(): user = mixer.blend('users.User', username='******') assert user.id is not None, 'User should exist in the database' assert user.username == 'John', 'User should have a username'
def test_rsvp_retreive(client): rsvp = mixer.blend('games.RsvpStatus') res = client.get(reverse('rsvp-detail', (rsvp.game.id, rsvp.id))) assert res.status_code == status.HTTP_200_OK, \ 'RsvpStatus can be accessed by any user'
def test_rsvp_update_by_user(client): RSVPS = [ RsvpStatus.REQUESTED_TO_JOIN, RsvpStatus.INVITED, RsvpStatus.NOT_GOING, RsvpStatus.UNCERTAIN, RsvpStatus.GOING, ] def valid_transactions(): return product(RSVPS[1:], RSVPS[2:]) def invalid_transactions(): return chain( product(RSVPS[2:], RSVPS[:2]), ((RsvpStatus.INVITED, RsvpStatus.REQUESTED_TO_JOIN), ), ) pickup_rsvp = mixer.blend('games.RsvpStatus', player=client.user) rsvp_url = reverse('rsvp-detail', (pickup_rsvp.game.id, pickup_rsvp.id)) for from_, to in valid_transactions(): pickup_rsvp.status = from_ pickup_rsvp.save() res = client.put(rsvp_url, {'rsvp': to}) assert res.status_code == status.HTTP_200_OK, \ 'Player should be able to change his status' for from_, to in invalid_transactions(): pickup_rsvp.status = from_ pickup_rsvp.save() res = client.put(rsvp_url, {'rsvp': to}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'Player should not set his status to invited or uncertain' team = mixer.blend('teams.Team') game = mixer.blend('games.Game', teams=[team]) team_rsvp = mixer.blend( 'games.RsvpStatus', game=game, player=client.user, team=0, ) team_rsvp_url = reverse('rsvp-detail', (team_rsvp.game.id, team_rsvp.id)) for from_, to in valid_transactions(): team_rsvp.status = from_ team_rsvp.save() res = client.put(team_rsvp_url, {'rsvp': to}) assert res.status_code == status.HTTP_200_OK, \ 'Player should be able to change his status' for from_, to in invalid_transactions(): team_rsvp.status = from_ team_rsvp.save() res = client.put(team_rsvp_url, {'rsvp': to}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'Player should not set his status to invited or uncertain' other_rsvp = mixer.blend('games.RsvpStatus') oher_url = reverse('rsvp-detail', (other_rsvp.game.id, other_rsvp.id)) for from_, to in product(RSVPS, RSVPS): other_rsvp.status = from_ other_rsvp.save() res = client.put(oher_url, {'rsvp': to}) assert res.status_code == status.HTTP_403_FORBIDDEN, \ 'Should not be able to access any other players rsvp'