def test__update_bet_split(self, mock_main): """When is_split is True, _update_bet should update the split row of the data table for the player. """ hands = [ cards.Hand([ cards.Card(11, 0), ]), cards.Hand([ cards.Card(11, 3), ]), ] player = players.Player(hands, name='spam', chips=100) player2 = players.Player(name='eggs', chips=100) new_data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', 20, 'J♠', 'Loses.'], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] exp = call().send(('update', new_data)) data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', '', 'J♠', ''], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui._update_bet(player, 20, 'Loses.', split=True) act = mock_main.mock_calls[-1] ui.end() self.assertEqual(exp, act)
def test_cleanup(self, mock_main): """When called, cleanup() should clear the bet, hand, and event field of every row in the data table, then send it to the UI. """ hands = [ cards.Hand([ cards.Card(11, 0), ]), cards.Hand([ cards.Card(11, 3), ]), ] player = players.Player(hands, name='spam', chips=100) player2 = players.Player(hands, name='eggs', chips=100) new_data = [ [player, 100, '', '', ''], [player2, 100, '', '', ''], ] exp = call().send(('update', new_data)) data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', 20, 'J♠', 'Splits hand.'], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.cleanup() act = mock_main.mock_calls[-1] self.assertEqual(exp, act)
def test_joins(self, mock_main): """When given a player, joins() should add the player to the data table in the first empty row. """ player = players.Player(name='spam', chips=100) player2 = players.Player(name='eggs', chips=100) new_data1 = [ [player, 100, '', '', 'Sits down.'], ['', '', '', '', ''], ] new_data2 = [ [player, 100, '', '', 'Sits down.'], [player2, 100, '', '', 'Sits down.'], ] exp_call = [ call().send(('update', new_data1)), call().send(('update', new_data2)), ] data = [ ['', '', '', '', ''], ['', '', '', '', ''], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.joins(player) ui.ctlr.data = new_data1 ui.joins(player2) act_call = mock_main.mock_calls[-2:] ui.end() self.assertEqual(exp_call, act_call) self.assertNotEqual(new_data2, new_data1)
def test_hand_updates(self, mock_update_hand, _): """The tested methods should call the _update_hand() method with the player, hand, and event text. """ player = players.Player(name='spam', chips=100) hand = cards.Hand([ cards.Card(11, 0), cards.Card(10, 3), ]) handstr = str(hand) exp = [ call(player, hand, 'Takes hand.'), call(player, hand, 'Flips card.'), call(player, hand, 'Hits.'), call(player, hand, 'Stands.'), ] data = [ [player, 80, 20, '', ''], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.deal(player, hand) ui.flip(player, hand) ui.hit(player, hand) ui.stand(player, hand) act = mock_update_hand.mock_calls[-4:] ui.end() self.assertEqual(exp, act)
def test__yesnos(self, mock_yesno, _): """The individual yes/no prompts should sent their prompt and a default response value to _yesno_prompt and return the response. """ exp_resp = model.IsYes('y') exp_calls = [ call('Double down?', 'y'), call('Hit?', 'y'), call('Buy insurance?', 'y'), call('Play another round?', 'y'), call('Split your hand?', 'y'), ] mock_yesno.return_value = exp_resp ui = cli.TableUI() ui.start() act_resps = [] act_resps.append(ui.doubledown_prompt()) act_resps.append(ui.hit_prompt()) act_resps.append(ui.insure_prompt()) act_resps.append(ui.nextgame_prompt()) act_resps.append(ui.split_prompt()) act_calls = mock_yesno.mock_calls[-5:] ui.end() for act_resp in act_resps: self.assertEqual(exp_resp, act_resp) for exp, act in zip(exp_calls, act_calls): self.assertEqual(exp, act)
def test__update_event(self, mock_main): """_update_event should send an event to the UI loop that a player has had an event occur. The data sent in that event should be a copy of the table in the termui.Table object. """ player = players.Player(name='spam', chips=80) msg = 'Walks away.' new_data = [ [player, 80, '', '', msg], ] exp = call().send(('update', new_data)) unexp_data = [ [player, 80, '', '', ''], ] ui = cli.TableUI() ui.ctlr.data = unexp_data ui.start() ui._update_event(player, msg) act = mock_main.mock_calls[-1] ui.end() self.assertEqual(exp, act) # Since termui.Table determines what fields to update based # on differences between it's data table and the data table # it's sent, it's very important that the changes made to # the data table output by _update_bet() are not yet seen in # the data table held by termui.Table. # # If this test fails, it's likely because you aren't copying # the rows of self.ctrl.data. You are referencing them. self.assertNotEqual(unexp_data[0][4], 'Takes hand.')
def test__update_hand_split(self, mock_main): """If sent a split hand, _update_hand() should update the split row of the table. """ hands = [ cards.Hand([ cards.Card(11, 0), ]), cards.Hand([ cards.Card(11, 3), ]), ] player = players.Player(hands, name='spam', chips=100) player2 = players.Player(name='eggs', chips=100) new_data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', 20, 'J♠ 5♣', 'Hits.'], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] exp = call().send(('update', new_data)) data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', 20, 'J♠', 'Splits hand.'], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() hands[1].append(cards.Card(5, 0)) ui._update_hand(player, hands[1], 'Hits.') act = mock_main.mock_calls[-1] ui.end() self.assertEqual(exp, act)
def test_init_optional_attrs(self): """On initialization, TableUI should accept optional attributes. """ fields = [ [ 'Name', '{:<10}', ], [ 'Value', '{:<10}', ], ] ctlr = termui.Table('spam', fields) exp = { 'ctlr': ctlr, 'seats': 6, } ui = cli.TableUI(**exp) for attr in exp: act = getattr(ui, attr) self.assertEqual(exp[attr], act)
def test_init_no_optional_attrs(self): """On initialization, TableUI should not require optional attributes. """ exp = termui.Table ui = cli.TableUI() act = ui.ctlr self.assertTrue(isinstance(act, exp))
def test_end(self, mock_main): """end() should terminate UI loop gracefully.""" exp = call().close() ui = cli.TableUI() ui.start() ui.end() act = mock_main.mock_calls[-1] self.assertEqual(exp, act)
def test_stand(self, mock_input): """When the user chooses to hit, will_hit_user() returns False. """ expected = False mock_input.return_value = model.IsYes(expected) ui = cli.TableUI() g = game.Engine(None, None, None, None, None) actual = willhit.will_hit_user(None, None, g) mock_input.assert_called() self.assertEqual(expected, actual)
def test__yesno_prompt_unit_valid(self, mock_main): """If the user responds with an invalid value, the prompt should be repeated. """ exp_resp = model.IsYes('n') ui = cli.TableUI() mock_main.return_value = (item for item in [None, None, 'z', ' ', 'n']) ui.start() act_resp = ui._yesno_prompt('spam', 'y') ui.end() self.assertEqual(exp_resp.value, act_resp.value)
def test___prompt_calls(self, mock_main): """When called, _prompt() should send the UI a prompt for user input and return the result. """ exp_call = call().send(('input', 'spam', 'y')) ui = cli.TableUI() ui.start() act_resp = ui._prompt('spam', 'y') act_call = mock_main.mock_calls[-1] ui.end() self.assertEqual(exp_call, act_call)
def test__yesno_prompt(self, mock_prompt, _): """When called, _yesno_prompt() should prompt the user for a yes/no answer. The response should be returned. """ exp_resp = model.IsYes('y') exp_call = call('Play another round? [yn] > ', 'y') ui = cli.TableUI() mock_prompt.return_value = 'y' ui.start() act_resp = ui._yesno_prompt('Play another round?', 'y') ui.end() act_call = mock_prompt.mock_calls[-1] self.assertEqual(exp_resp.value, act_resp.value) self.assertEqual(exp_call, act_call)
def test_start(self, mock_main): """start() should kick off the main loop of the UI, set it as the loop attribute, and prime it. """ ui = cli.TableUI() term = ui.ctlr exp = [ call(ui.ctlr, False), call().__next__(), call().send(('draw', )) ] ui.start() act = mock_main.mock_calls self.assertEqual(exp, act)
def test_reset(self, mock_main): """When called, reset() should terminate the existing controller, create a new one, and prime it. """ ui = cli.TableUI() ui.start() ui.reset() reset_ctlr = ui.ctlr exp = [ call().close(), call(reset_ctlr, False), call().__next__(), call().send(('draw', )), ] act = mock_main.mock_calls[-4:] ui.end() self.assertListEqual(exp, act)
def test_event_updates(self, mock_update_event, _): """The tested methods should call the _update_event() method with the player and event text. """ player = players.Player(name='spam', chips=100) exp = [ call(player, 'Shuffles the deck.'), ] data = [ [player, 80, 20, '', ''], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.shuffles(player) act = mock_update_event.mock_calls[-1:] ui.end() self.assertEqual(exp, act)
def test_bet_updates(self, mock_update_bet, _): """The tested methods should call the _update_bet() method with the player, bet, and event text. """ player = players.Player(name='spam', chips=100) bet = 20 exp = [ call(player, bet, 'Bets.'), call(player, bet, 'Doubles down.'), call(player, bet, f'Buys {bet} insurance.'), call(player, bet, f'Insurance pays {bet}.'), call(player, '', 'Loses.'), call(player, '', 'Loses.', True), call(player, '', f'Ties {bet}.'), call(player, '', f'Wins {bet}.'), call(player, '', f'Ties {bet}.', True), call(player, '', f'Wins {bet}.', True), ] data = [ [player, 80, 20, '', ''], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.bet(player, bet) ui.doubledown(player, bet) ui.insures(player, bet) ui.insurepay(player, bet) ui.loses(player) ui.loses_split(player) ui.tie(player, bet) ui.wins(player, bet) ui.ties_split(player, bet) ui.wins_split(player, bet) act = mock_update_bet.mock_calls[-10:] ui.end() self.assertEqual(exp, act)
def test_splits(self, mock_main): """When given a player and a bet, splits() should add a row to the data table for the split hand, update it with the relevant information, and send it to the UI. """ hands = [ cards.Hand([ cards.Card(11, 0), ]), cards.Hand([ cards.Card(11, 3), ]), ] player = players.Player(hands, name='spam', chips=100) player2 = players.Player(hands, name='eggs', chips=100) new_data = [ [player, 100, 20, 'J♣', 'Splits hand.'], [' \u2514\u2500', '', 20, 'J♠', ''], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] exp_call = call().send(('update', new_data)) unexp_len = len(new_data) data = [ [player, 100, 20, 'J♣ J♠', 'Takes hand.'], [player2, 100, 20, '3♣ 4♣', 'Takes hand.'], ] ui = cli.TableUI() ui.ctlr.data = data ui.start() ui.splits(player, 20) act_call = mock_main.mock_calls[-1] act_len = len(data) ui.end() self.assertEqual(exp_call, act_call) self.assertNotEqual(unexp_len, act_len)
def test_leaves(self, mock_main): """When given a player, leaves() should announce the player is leaving and remove the player from the data table. In order to avoid the row in the UI just going blank, this call will edit self.ctlr.data directly. """ player = players.Player(name='spam', chips=100) player2 = players.Player(name='eggs', chips=100) new_data = [ [player, '', '', '', 'Walks away.'], [player2, 100, '', '', 'Sits down.'], ] exp_call = call().send(('update', new_data)) exp_data = [ ['', '', '', '', 'Walks away.'], [player2, 100, '', '', 'Sits down.'], ] data = [ [player, 100, '', '', 'Sits down.'], [player2, 100, '', '', 'Sits down.'], ] ui = cli.TableUI() ui.ctlr.data = data def update_data(ctlr, data): ctlr.data = data mock_main.side_effect = update_data(ui.ctlr, [r[:] for r in new_data]) ui.start() ui.leaves(player) act_call = mock_main.mock_calls[-1] act_data = ui.ctlr.data ui.end() self.assertEqual(exp_call, act_call) self.assertEqual(exp_data, act_data)