def test_resumes_players(self): s = persistent.State("arbitrary-tourney-id") p = data.Player(123, "challonge_id", 1) s.add_players([p]) # pretend we crashed, this is the "reloaded" one. new_s = persistent.State("arbitrary-tourney-id") self.assertEqual(1, len(new_s.players)) self.assertEqual(p, new_s.players[0])
def test_add_players_to_bracket(self): p1_name, p2_name = "Alice", "Bob" p1_challonge_id, p2_challonge_id = "1001", "1002" # Challonge IDs p1_discord_id, p2_discord_id = 1, 2 # Discord IDs # Fake challonge call, will succeed mock_challonge = unittest.mock.MagicMock(spec=challonge.Client) mock_challonge.add_players = unittest.mock.MagicMock( return_value={ p1_name: p1_challonge_id, p2_name: p2_challonge_id, }) state = persistent.State("arbitraryID12") bracket = Bracket(mock_challonge, state) # Create the players. bracket.create_players({ p1_discord_id: p1_name, p2_discord_id: p2_name, }) self.assertEqual(2, len(bracket.players)) self.assertEqual(p1_discord_id, bracket.players[0].discord_id) self.assertEqual(p1_challonge_id, bracket.players[0].challonge_id) self.assertEqual(p2_discord_id, bracket.players[1].discord_id) self.assertEqual(p2_challonge_id, bracket.players[1].challonge_id)
def test_resumes_called_matches(self): tourney_id = "some-tourney-id" tourney_link = "challonge.com/arbitrary-link" match_id = "some-match-id" # State with 1 match called. m = data.new_match(data.new_player(0, "arbitrary-id1"), data.new_player(1, "arbitrary-id2"), match_id) m.call_time = datetime.now() s = persistent.State(tourney_id, tourney_link) s.set_matches([m]) # pretend we crashed new_s = persistent.State(tourney_id) # Same tourney ID as before. self.assertEqual(1, len(new_s.known_matches)) self.assertIsNotNone(new_s.known_matches[0].call_time) self.assertEqual(tourney_link, new_s.bracket_link)
def test_pings_uncalled_players_exactly_once(self): p1_name, p2_name = "Alice", "Bob" # Discord names. p1_discord_id, p2_discord_id = 1, 2 # Discord IDs. p1_challonge_id, p2_challonge_id = "1001", "1002" # Challonge IDs. # Set "challonge" up to add Alice and Bob. mock_challonge = unittest.mock.MagicMock(spec=challonge.Client) mock_challonge.add_players = unittest.mock.MagicMock( return_value={ p1_name: p1_challonge_id, p2_name: p2_challonge_id, }) # Set "challonge" up to have 1 in progress match. match = challonge.Match("arbitrary_match_id", p1_challonge_id, p2_challonge_id) mock_challonge.list_matches = unittest.mock.MagicMock( return_value=[match]) # Not mocked, we're testing real logic here. state = persistent.State("arbitraryID12") bracket = Bracket(mock_challonge, state) # Mock out external dependencies. mock_discord_client = unittest.mock.MagicMock( spec=discord.ext.commands.Bot) output_channel = unittest.mock.MagicMock(spec=discord.TextChannel) output_channel.send.return_value.id = 1234 # Add players to the bracket. bracket.create_players({ p1_discord_id: p1_name, p2_discord_id: p2_name, }) bot = main.Tournament(mock_discord_client, bracket, 4206969, output_channel) _wait_for(bot.check_matches()) # Players should have been pinged, as there is 1 in-progress match that hasn't been called. output_channel.send.assert_called_once() self.assertIn(f"<@!{p1_discord_id}>", output_channel.send.call_args[0][0]) self.assertIn(f"<@!{p2_discord_id}>", output_channel.send.call_args[0][0]) # Check again. Because we already pinged the players once, they should not have been called again. output_channel.send.reset_mock() _wait_for(bot.check_matches()) output_channel.send.assert_not_called()
def create(api_token: str, name: str, admin_id: int, tournament_type=challonge.TourneyType.DOUBLE_ELIM, is_unlisted=True): """ Creates a new tournament in Challonge owned by the user with the given API key. name can only contain letters, numbers, and underscores. Returns a new Tournament object corresponding to the created tournament. """ challonge_client = challonge.Client(api_token) tourney_id, url = challonge_client.create_tournament( name, tournament_type, is_unlisted) state = persistent.State(tourney_id, url) state.set_admin(admin_id) return Bracket(challonge_client, state)
def test_dq_both_players(self): """ Scenario in which neither player checks into their match. Asserts: 1. Both players are warned. 2. A score is set after the DQ interval. 3. No further messages are sent after that. """ warn_timer_in_secs = 1 dq_timer_in_secs = 2 emoji = "😀" # 2 Players, Alice and Bob. p1_name, p2_name = "Alice", "Bob" # Discord names. p1_discord_id, p2_discord_id = 1, 2 # Discord IDs. p1_challonge_id, p2_challonge_id = "1001", "1002" # Challonge IDs. tourney_id = "tourneyID12" # Set "challonge" up to add Alice and Bob. mock_challonge = unittest.mock.MagicMock(spec=challonge.Client) mock_challonge.add_players = unittest.mock.MagicMock( return_value={ p1_name: p1_challonge_id, p2_name: p2_challonge_id, }) # Set "challonge" up to have 1 in progress match (Alice vs Bob). match_id = "arbitrary_match_id" match = challonge.Match(match_id, p1_challonge_id, p2_challonge_id) mock_challonge.list_matches = unittest.mock.MagicMock( return_value=[match]) # Not mocked, we're testing real logic here. state = persistent.State(tourney_id) bracket = Bracket(mock_challonge, state) # Mock out external dependencies. mock_discord_client = unittest.mock.MagicMock( spec=discord.ext.commands.Bot) output_channel = unittest.mock.MagicMock(spec=discord.TextChannel) # Add players to the bracket. bracket.create_players({ p1_discord_id: p1_name, p2_discord_id: p2_name, }) bot = main.Tournament( mock_discord_client, bracket, 4206969, output_channel, options=main.Options( warn_timer_in_minutes=warn_timer_in_secs / 60, dq_timer_in_minutes=dq_timer_in_secs / 60, check_in_emoji=discord.PartialEmoji(name=emoji))) # Call the match. Set the ID to be returned from the sent message, so we can reference it later. match_call_message = unittest.mock.MagicMock(spec=discord.Message) match_call_message.id = 6942096 output_channel.send.return_value = match_call_message _wait_for(bot.check_matches()) output_channel.send.assert_called_once() self.assertIn(f"<@!{p1_discord_id}>", output_channel.send.call_args[0][0]) self.assertIn(f"<@!{p2_discord_id}>", output_channel.send.call_args[0][0]) # Neither player checks in. match_call_message.reactions = [_reaction(emoji)] util.get_user_ids = lambda _: _future({}) output_channel.fetch_message.return_value = match_call_message # 1. Both players should be warned. output_channel.send.reset_mock() time.sleep(warn_timer_in_secs) _wait_for(bot.check_matches()) output_channel.fetch_message.assert_called_with(match_call_message.id) self.assertGreaterEqual(output_channel.send.call_count, 2) self.assertIn(f"<@!{p1_discord_id}>", output_channel.send.call_args_list[0][0][0]) self.assertIn(f"<@!{p2_discord_id}>", output_channel.send.call_args_list[1][0][0]) # Nobody should have been DQ'd yet. mock_challonge.set_score.assert_not_called() # Wait until DQ deadline, nobody checks in still. time.sleep(dq_timer_in_secs - warn_timer_in_secs + 1) output_channel.send.reset_mock() _wait_for(bot.check_matches()) # 2. Make sure a score was set for the match so it doesn't hold up the bracket. output_channel.send.assert_called_once() mock_challonge.set_score.assert_called() # Let's assume that set_score failed, and so the match is still # returned by challonge.list_matches. # 3. Make sure we don't message the players again. output_channel.send.reset_mock() _wait_for(bot.check_matches()) output_channel.send.assert_not_called()
def resume(api_token: str, tournament_id: str): client = challonge.Client(api_token) return Bracket(client, persistent.State(tournament_id))