class MockFrontend(Frontend): def __init__(self): self._gamedb = None def start_game(self, tiktok: Text, phone_number: Text, game_hashtag: Text): game_id = FirestoreDB.add_game( json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH, hashtag=game_hashtag) self._gamedb = FirestoreDB( json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH, game_id=game_id) self.join_game(tiktok=tiktok, phone_number=phone_number, game_id=game_id) def _verify_game_started(self): if not self._gamedb: raise TestError('Must call start_game to create a game_id.') def join_game(self, tiktok: Text, phone_number: Text, game_id: Text) -> None: name = tiktok self._verify_game_started() self._gamedb.player(name=name, tiktok=tiktok, phone_number=phone_number) def submit_entry(self, likes: int, views: int, player_id: Text, tribe_id: Text, challenge_id: Text, team_id: Text, url: Text) -> None: self._verify_game_started() self._gamedb.add_challenge_entry( database.Entry(likes=likes, views=views, player_id=player_id, tribe_id=tribe_id, challenge_id=challenge_id, team_id=team_id, url=url)) def submit_challenge(self, from_player_id: Text, challenge_name: Text, challenge_message: Text) -> None: self._verify_game_started()
def test_integration(self): test_id = str(uuid.uuid4()) # Inject a game ID (test uuid) into the gamedb. use a globally unique country code to ensure # that only this game gets scheduled. game_id = FirestoreDB.add_game( json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH, hashtag=_TEST_GAME_HASHTAG, country_code=f'US-{test_id}') gamedb = FirestoreDB( json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH, game_id=game_id) log_message(f'Running integration test for game {game_id}') # create an integration test subsystem log stream that specifically captures # game inputs and outputs at the SMS boundary. test_log_stream = GameIntegrationTestLogStream(game_id=game_id, test_id=test_id) # add test challenges for challenge in _TEST_CHALLENGES: gamedb.add_challenge(challenge=challenge) # if non-existent, create users associated with players. NOTE: critical for FE code # to create users when players sign up. for player_info in [*_EMULATED_PLAYERS, *_REAL_PLAYERS]: FirestoreDB.add_user( json_config_path=_TEST_FIRESTORE_INSTANCE_JSON_PATH, name=player_info[0], tiktok=player_info[1], phone_number=player_info[2]) # Inject players into gamedb. set the phone number of the players to a known, or emulated device. emulated_players = [] for player_info in _EMULATED_PLAYERS: player = gamedb.player(name=player_info[0], tiktok=player_info[1], phone_number=player_info[2]) emulated_players.append( EmulatedPlayer(id=player.id, name=player.name, tiktok=player.tiktok, phone_number=player.phone_number, test_stream=test_log_stream, gamedb=gamedb)) for player_info in _REAL_PLAYERS: player = gamedb.player(name=player_info[0], tiktok=player_info[1], phone_number=player_info[2]) # mock the scheduling method in MM service so that we can force schedule # after initialization. save_check_start_time_fn = MatchmakerService._check_start_time check_start_time_fn = mock.MagicMock() check_start_time_fn.return_value = False MatchmakerService._check_start_time = check_start_time_fn # create device emulator for Twilio SMS events. patch this # into the game engine class for the test. notification_emulator = FakeTwilioSMSNotifier( json_config_path=_TEST_TWILIO_SMS_CONFIG_PATH, game_id=game_id, emulated_devices=emulated_players) build_notifier_fn = mock.MagicMock() build_notifier_fn.return_value = notification_emulator Engine._get_sms_notifier = build_notifier_fn # Instantiate a local matchmaker service. make sure all services have the right configs, # e.g. twilio should be using the prod service phone number so that it can actually send messages. # set the clock mode on (2) to async so that game events happen immediately during testing. service = MatchmakerService( matchmaker=MatchMakerRoundRobin(), region=f'US-{test_id}', gamedb=gamedb, game_options=GameOptions( game_clock_mode=GameClockMode.ASYNC, game_wait_sleep_interval_sec=_TEST_SLEEP_INTERVAL, multi_tribe_min_tribe_size=2, engine_worker_thread_count=5, tribe_council_time_sec=_TEST_SLEEP_INTERVAL)) # mock the MM Twilio client service._get_sms_notifier = mock.MagicMock( return_value=notification_emulator) try: service.start_matchmaker_daemon(sleep_seconds=1) # force schedule the game in MM (1). check_start_time_fn.return_value = True MatchmakerService._check_start_time = check_start_time_fn while gamedb.game_from_id(game_id).count_players > 1: time.sleep(_TEST_SLEEP_INTERVAL) finally: MatchmakerService._check_start_time = save_check_start_time_fn service.set_stop() test_dict = test_log_stream.to_dict() if _SAVE_TEST_LOGS: persisted_test_logs = test_log_stream.persist() log_message(persisted_test_logs) with open(f'game_logs/stream.{test_id}.json', 'w+') as f: f.write(persisted_test_logs) active_players = list() for player in gamedb.stream_players( active_player_predicate_value=True): active_players.append(player) winner = active_players[0] found_winner_message = False for output in test_dict['outputs']: if 'You are the last survivor and WINNER' in output[ 'message'] and output['name'] == winner.name: found_winner_message = True self.assertTrue(found_winner_message)