"""Behavioral coverage for the alpha 0.6.2 latency and blackjack fixes.""" import json import tempfile import unittest from pathlib import Path from unittest import mock from test_jwebot_edge import MODULE, config class Release062BlackjackTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.engine = MODULE.EdgeApplication(config(Path(self.temp.name))) self.counter = 0 def tearDown(self): self.engine.ledger.connection.close() self.temp.cleanup() def command(self, question, *, event_id=None, sender="Alice"): self.counter += 1 row = { "question": question, "sender": sender, "group_fingerprint": "group-a", "event_id": event_id or f"test-{self.counter}", } return self.engine.local.handle(row, {}) def state(self, sender="Alice"): key = self.engine.ledger.resolve_person("group-a", sender)["person_key"] row = self.engine.ledger.connection.execute( """ SELECT state_json FROM player_accounts WHERE group_fingerprint = ? AND person_key = ? """, ("group-a", key), ).fetchone() return json.loads(row[0]) @staticmethod def hit_deck(cards): first = [4, 5, 8, 7] cards[:] = ( first + [card for card in cards if card not in first and card != 1] + [1] ) def test_compact_start_sets_stake_then_separate_hit_replays_once(self): with mock.patch.object( self.engine.local.players.rng, "shuffle", side_effect=self.hit_deck, ): start = self.command("/21点开始100", event_id="compact-start") self.assertTrue(start.startswith("alice #1:")) self.assertIn("下注 100", start) self.assertEqual(self.state()["balance"], 900) self.assertEqual(len(self.state()["game"]["player"]), 2) first = self.command("/21点要牌", event_id="separate-hit") replay = self.command( "/21点 要牌", event_id="separate-hit", sender="a1", ) self.assertEqual(replay, first) self.assertTrue(first.startswith("alice #1:")) self.assertIn("13点", first) self.assertEqual(self.state()["balance"], 900) self.assertEqual(len(self.state()["game"]["player"]), 3) def test_spaced_chinese_and_compact_english_start_use_bet(self): def tied_deck(cards): first = [9, 6, 8, 7] cards[:] = first + [card for card in cards if card not in first] for command, sender in ( ("/21点 开始 50", "Alice"), ("/blackjackstart50", "Bob"), ): with self.subTest(command=command): with mock.patch.object( self.engine.local.players.rng, "shuffle", side_effect=tied_deck, ): started = self.command(command, sender=sender) self.assertTrue( started.startswith( "alice #1:" if sender == "Alice" else "bob #1:" ) ) self.assertIn("下注 50", started) self.assertEqual(self.state(sender)["balance"], 950) self.assertIsNotNone(self.state(sender)["game"]) self.command("/21点 结束", sender=sender) self.assertIsNone(self.state(sender)["game"]) def test_default_bet_can_start_without_spaces(self): with mock.patch.object( self.engine.local.players.rng, "shuffle", side_effect=self.hit_deck, ): reply = self.command("/21点开始") self.assertTrue(reply.startswith("alice #1:")) self.assertIn("下注 50", reply) self.assertEqual(self.state()["balance"], 950) def test_combined_start_and_action_explains_two_step_flow(self): reply = self.command("/21点开始100要牌") self.assertIn("分两步", reply) self.assertIn("100 是本局下注", reply) self.assertIn("再单独发送", reply) wallet = self.command("/摩拉") self.assertIn("摩拉 1000", wallet) self.assertIn("无进行中的牌局", wallet) if __name__ == "__main__": unittest.main()