def test_line_charts(self): # TODO: This test throws errors related to missing data in games 1 and 4. For now we're not worried about this, # since game #3 is our realistic test case, but could be worth going back and debugging later. game_id = 3 user_ids = [1, 3, 4] compile_and_pack_player_leaderboard(game_id) with patch("backend.logic.base.time") as mock_base_time: mock_base_time.time.return_value = simulation_end_time make_the_field_charts(game_id) # this is basically the internals of async_update_all_games for one game for user_id in user_ids: serialize_and_pack_pending_orders(game_id, user_id) serialize_and_pack_portfolio_details(game_id, user_id) # Verify that the JSON objects for chart visuals were computed and cached as expected field_chart = s3_cache.unpack_s3_json("3/field_chart") self.assertIsNotNone(field_chart) self.assertIsNotNone(s3_cache.unpack_s3_json("3/1/current_balances")) self.assertIsNotNone(s3_cache.unpack_s3_json("3/3/current_balances")) self.assertIsNotNone(s3_cache.unpack_s3_json("3/4/current_balances")) # verify chart information test_user_data = [ x for x in field_chart["datasets"] if x["label"] == "cheetos" ][0] self.assertLessEqual(len(test_user_data["data"]), N_PLOT_POINTS)
def test_single_player_visuals(self, mock_base_time, mock_game_time): mock_base_time.time.return_value = mock_game_time.time.return_value = simulation_end_time game_id = 8 user_id = 1 serialize_and_pack_pending_orders(game_id, user_id) serialize_and_pack_order_performance_assets(game_id, user_id) pending_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{user_id}/{PENDING_ORDERS_PREFIX}") fulfilled_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{user_id}/{FULFILLED_ORDER_PREFIX}") self.assertEqual(len(pending_orders_table["data"]), 0) self.assertEqual(len(fulfilled_orders_table["data"]), 2) self.assertEqual( set([x["Symbol"] for x in fulfilled_orders_table["data"]]), {"NVDA", "NKE"}) serialize_and_pack_order_performance_assets(game_id, user_id) self.assertIn(f"{game_id}/{user_id}/{ORDER_PERF_CHART_PREFIX}", s3_cache.keys()) op_chart = s3_cache.unpack_s3_json( f"{game_id}/{user_id}/{ORDER_PERF_CHART_PREFIX}") chart_stocks = set( [x["label"].split("/")[0] for x in op_chart["datasets"]]) expected_stocks = {"NKE", "NVDA"} self.assertEqual(chart_stocks, expected_stocks) # balances chart df = make_user_balances_chart_data(game_id, user_id) serialize_and_pack_balances_chart(df, game_id, user_id) balances_chart = s3_cache.unpack_s3_json( f"{game_id}/{user_id}/{BALANCES_CHART_PREFIX}") self.assertEqual(set([x["label"] for x in balances_chart["datasets"]]), {"NVDA", "NKE", "Cash"}) # leaderboard and field charts compile_and_pack_player_leaderboard(game_id) make_the_field_charts(game_id) field_chart = s3_cache.unpack_s3_json( f"{game_id}/{FIELD_CHART_PREFIX}") _index_names = query_to_dict("SELECT * FROM index_metadata") _index_names = [x["name"] for x in _index_names] self.assertEqual(set([x["label"] for x in field_chart["datasets"]]), set(["cheetos"] + _index_names))
def test_visuals_after_hours(self): game_id = 5 start_time = 1591923966 self._start_game_runner(start_time, game_id) # These are the internals of the celery tasks that called to update their state serialize_and_pack_pending_orders(game_id, self.user_id) pending_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{PENDING_ORDERS_PREFIX}") self.assertEqual(pending_orders_table["data"][0]["Symbol"], self.stock_pick) self.assertEqual(len(pending_orders_table["data"]), 1) fulfilled_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{FULFILLED_ORDER_PREFIX}") self.assertEqual(fulfilled_orders_table["data"], []) serialize_and_pack_portfolio_details(game_id, self.user_id) current_balances = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{CURRENT_BALANCES_PREFIX}") self.assertEqual(len(current_balances["data"]), 0) with patch("backend.logic.base.time") as base_time_mock: base_time_mock.time.side_effect = [start_time] * 2 * 2 df = make_user_balances_chart_data(game_id, self.user_id) serialize_and_pack_balances_chart(df, game_id, self.user_id) balances_chart = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{BALANCES_CHART_PREFIX}") self.assertEqual(len(balances_chart["datasets"]), 1) self.assertEqual(balances_chart["datasets"][0]["label"], "Cash") self.assertEqual(balances_chart["datasets"][0]["backgroundColor"], NULL_RGBA) compile_and_pack_player_leaderboard(game_id) leaderboard = s3_cache.unpack_s3_json( f"{game_id}/{LEADERBOARD_PREFIX}") self.assertTrue( all([ x["cash_balance"] == STARTING_VIRTUAL_CASH for x in leaderboard["records"] ]))
def make_leaderboard_with_context(**context): game_id, start_time, end_time = context_parser(context, "game_id", "start_time", "end_time") start_time, end_time = get_time_defaults(game_id, start_time, end_time) compile_and_pack_player_leaderboard(game_id, start_time, end_time)
def test_visuals_during_trading(self): # TODO: Add a canonical test with fully populated data """When a user first places an order, we don't necessarily expect that security to have generated any data, yet. There should be a blank chart until data is available """ game_id = 5 start_time = simulation_start_time self._start_game_runner(start_time, game_id) # now have a user put in a couple orders. Valid market orders should clear and reflect in the balances table, # valid stop/limit orders should post to pending orders serialize_and_pack_pending_orders(game_id, self.user_id) pending_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{PENDING_ORDERS_PREFIX}") fulfilled_orders_table = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{FULFILLED_ORDER_PREFIX}") # since the order has been filled, we expect a clear price to be present self.assertNotEqual(fulfilled_orders_table["data"][0]["Clear price"], NA_TEXT_SYMBOL) self.assertEqual(fulfilled_orders_table["data"][0]["Symbol"], self.stock_pick) self.assertEqual(pending_orders_table["data"], []) self.assertEqual(len(fulfilled_orders_table["data"]), 1) serialize_and_pack_portfolio_details(game_id, self.user_id) current_balances = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{CURRENT_BALANCES_PREFIX}") self.assertEqual(len(current_balances["data"]), 1) with patch("backend.logic.base.time") as base_time_mock: base_time_mock.time.side_effect = [start_time + 10] * 2 * 2 df = make_user_balances_chart_data(game_id, self.user_id) serialize_and_pack_balances_chart(df, game_id, self.user_id) balances_chart = s3_cache.unpack_s3_json( f"{game_id}/{self.user_id}/{BALANCES_CHART_PREFIX}") self.assertEqual(len(balances_chart["datasets"]), 2) stocks = set([x["label"] for x in balances_chart["datasets"]]) self.assertEqual(stocks, {"Cash", self.stock_pick}) self.assertNotIn( NULL_RGBA, [x["backgroundColor"] for x in balances_chart["datasets"]]) compile_and_pack_player_leaderboard(game_id) leaderboard = s3_cache.unpack_s3_json( f"{game_id}/{LEADERBOARD_PREFIX}") user_stat_entry = [ x for x in leaderboard["records"] if x["id"] == self.user_id ][0] self.assertEqual(user_stat_entry["cash_balance"], STARTING_VIRTUAL_CASH - self.market_price) self.assertTrue( all([ x["cash_balance"] == STARTING_VIRTUAL_CASH for x in leaderboard["records"] if x["id"] != self.user_id ])) fulfilled_orders_table = s3_cache.unpack_s3_json( f'{game_id}/{self.user_id}/{FULFILLED_ORDER_PREFIX}') self.assertIn("order_label", fulfilled_orders_table["data"][0].keys()) self.assertIn("color", fulfilled_orders_table["data"][0].keys())