summaryrefslogtreecommitdiffstats
path: root/tests/client_core.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-29 18:22:40 +0100
committersalmonik <salmonik@tuta.io>2026-10-29 18:22:40 +0100
commitb5a52fc0312afdf5d5fbe53275dc88d6d881c2ff (patch)
treed12e3c7f6c23ae1698199d16ee763551edfd8c12 /tests/client_core.rs
parentv2.1.2: ignore ANSI when measuring board height (diff)
downloadzagan-bet-b5a52fc0312afdf5d5fbe53275dc88d6d881c2ff.tar.gz
zagan-bet-b5a52fc0312afdf5d5fbe53275dc88d6d881c2ff.zip
v2.2.0: add blackjack with reserved bets and hit/stand/double
Diffstat (limited to 'tests/client_core.rs')
-rw-r--r--tests/client_core.rs201
1 files changed, 200 insertions, 1 deletions
diff --git a/tests/client_core.rs b/tests/client_core.rs
index 7fb7e29..cfcf608 100644
--- a/tests/client_core.rs
+++ b/tests/client_core.rs
@@ -4,8 +4,9 @@
4//! logical `Effect`s that `ClientCore` emits, so assertions are about what a 4//! logical `Effect`s that `ClientCore` emits, so assertions are about what a
5//! player would see, not about ANSI sequences. 5//! player would see, not about ANSI sequences.
6 6
7use zagan_bet::blackjack::BlackjackState;
7use zagan_bet::client::core::{ClientCore, Effect, InteractiveCommand, Key}; 8use zagan_bet::client::core::{ClientCore, Effect, InteractiveCommand, Key};
8use zagan_bet::client::games::response::parse_spin_response; 9use zagan_bet::client::games::response::{parse_blackjack_response, parse_spin_response};
9use zagan_bet::client::ui::command_names; 10use zagan_bet::client::ui::command_names;
10 11
11const WIN3: &str = "CCCCLLCLODGSDGS"; 12const WIN3: &str = "CCCCLLCLODGSDGS";
@@ -139,6 +140,11 @@ impl Harness {
139 self.line("play roulette"); 140 self.line("play roulette");
140 self.reply("INFO alice 1 1000"); 141 self.reply("INFO alice 1 1000");
141 } 142 }
143
144 fn enter_blackjack(&mut self) {
145 self.line("play blackjack");
146 self.reply("INFO alice 1 1000");
147 }
142} 148}
143 149
144#[test] 150#[test]
@@ -647,3 +653,196 @@ fn roulette_rejects_an_out_of_range_number() {
647 assert!(h.board()[4].contains("ERROR: Number must be 0-36")); 653 assert!(h.board()[4].contains("ERROR: Number must be 0-36"));
648 assert!(h.board()[2].contains("Bets: (none)")); 654 assert!(h.board()[2].contains("Bets: (none)"));
649} 655}
656
657fn bj_state(
658 session: &str,
659 phase: &str,
660 player: &[&str],
661 dealer: &[&str],
662 player_total: u8,
663 dealer_total: u8,
664 bet: u64,
665 base_bet: u64,
666 balance: i64,
667 actions: &[&str],
668 result: &str,
669 winnings: u64,
670) -> BlackjackState {
671 BlackjackState {
672 session_id: session.to_string(),
673 phase: phase.to_string(),
674 player: player.iter().map(|card| card.to_string()).collect(),
675 dealer: dealer.iter().map(|card| card.to_string()).collect(),
676 player_total,
677 dealer_total,
678 bet,
679 base_bet,
680 balance,
681 actions: actions.iter().map(|action| action.to_string()).collect(),
682 result: result.to_string(),
683 winnings,
684 }
685}
686
687#[test]
688fn blackjack_deals_hits_and_settles() {
689 let mut h = Harness::new();
690 h.enter_blackjack();
691
692 assert_eq!(h.board().len(), 6);
693 assert!(h.board()[4].contains("Press [SPACE] to deal."));
694
695 h.key(Key::Char(' '));
696 assert!(h
697 .sent
698 .iter()
699 .any(|line| line == "PLAY_START blackjack 10"));
700
701 let player = bj_state(
702 "bj1",
703 "player",
704 &["10S", "6H"],
705 &["9D", "?"],
706 16,
707 9,
708 10,
709 10,
710 990,
711 &["hit", "stand", "double"],
712 "playing",
713 0,
714 );
715 h.reply(&format!(
716 "BLACKJACK_STATE {}",
717 serde_json::to_string(&player).unwrap()
718 ));
719
720 assert_eq!(h.board().len(), 6);
721 assert!(h.board()[2].contains("Dealer: [9♦] [ ? ] 9"));
722 assert!(h.board()[3].contains("You: [10♠] [6♥] 16"));
723 assert!(h.board()[4].contains("Hit, stand or double."));
724 assert!(h.board()[5].contains("[D]ouble"));
725
726 h.key(Key::Char('h'));
727 assert_eq!(
728 h.sent.last().map(String::as_str),
729 Some("BLACKJACK_ACTION bj1 hit")
730 );
731
732 let done = bj_state(
733 "bj1",
734 "done",
735 &["10S", "6H", "5D"],
736 &["9D", "8C"],
737 21,
738 17,
739 10,
740 10,
741 1010,
742 &[],
743 "win",
744 20,
745 );
746 h.reply(&format!(
747 "BLACKJACK_STATE {}",
748 serde_json::to_string(&done).unwrap()
749 ));
750
751 assert!(h.board()[4].contains("Win! Won 20 PLN"));
752 assert!(h.board()[5].contains("[SPACE] New hand"));
753
754 h.key(Key::Char('q'));
755 assert!(h.board().is_empty());
756 assert!(h.screen.lines.iter().any(|line| line == "Game exited."));
757}
758
759#[test]
760fn blackjack_cancel_sends_a_cancel_action() {
761 let mut h = Harness::new();
762 h.enter_blackjack();
763 h.key(Key::Char(' '));
764
765 let player = bj_state(
766 "bj1",
767 "player",
768 &["10S", "6H"],
769 &["9D", "?"],
770 16,
771 9,
772 10,
773 10,
774 990,
775 &["hit", "stand", "double"],
776 "playing",
777 0,
778 );
779 h.reply(&format!(
780 "BLACKJACK_STATE {}",
781 serde_json::to_string(&player).unwrap()
782 ));
783
784 h.key(Key::Char('q'));
785 assert_eq!(
786 h.sent.last().map(String::as_str),
787 Some("BLACKJACK_ACTION bj1 cancel")
788 );
789
790 let cancelled = bj_state(
791 "bj1",
792 "done",
793 &["10S", "6H"],
794 &["9D", "?"],
795 16,
796 9,
797 10,
798 10,
799 1000,
800 &[],
801 "cancelled",
802 0,
803 );
804 h.reply(&format!(
805 "BLACKJACK_STATE {}",
806 serde_json::to_string(&cancelled).unwrap()
807 ));
808
809 assert!(h.board().is_empty());
810 assert!(h.screen.lines.iter().any(|line| line == "Game exited."));
811}
812
813#[test]
814fn blackjack_ready_board_can_change_the_next_bet() {
815 let mut h = Harness::new();
816 h.enter_blackjack();
817
818 h.key(Key::Char('='));
819 assert!(h.board()[1].contains("Bet: 20 PLN"));
820
821 h.key(Key::Char(' '));
822 assert!(h
823 .sent
824 .iter()
825 .any(|line| line == "PLAY_START blackjack 20"));
826}
827
828#[test]
829fn parses_a_blackjack_state() {
830 let state = bj_state(
831 "bj1",
832 "player",
833 &["10S", "6H"],
834 &["9D", "?"],
835 16,
836 9,
837 10,
838 10,
839 990,
840 &["hit", "stand"],
841 "playing",
842 0,
843 );
844 let response = format!("BLACKJACK_STATE {}", serde_json::to_string(&state).unwrap());
845
846 assert_eq!(parse_blackjack_response(&response).unwrap(), state);
847 assert!(parse_blackjack_response("ERROR Insufficient balance").is_err());
848}