summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-01 21:09:56 +0100
committersalmonik <salmonik@tuta.io>2026-11-01 21:09:56 +0100
commitbf4cf78ab26896faf457273e37d30fc96381c4a4 (patch)
tree71d67c300b6be191016a988ed5338e15c8b1bdd3 /tests
parentv4.1.1: pointer-first betting and visible payouts in the GUI (diff)
downloadzagan-bet-bf4cf78ab26896faf457273e37d30fc96381c4a4.tar.gz
zagan-bet-bf4cf78ab26896faf457273e37d30fc96381c4a4.zip
v4.2.0: wire the GUI to the core, transport and all four games
Phase 4. The egui frontend now shares ClientCore and the client database with the terminal: one background worker owns TLS, trust answers go through a channel, and a 10 s request deadline mirrors the terminal socket timeout. First contact, a changed key and a version mismatch are explicit screens; login can remember the credential and auto-login signs in before the login form appears. Adds the lobby with an update notice, a full-width scrollable history table, and the four games painted from View: slots with reel animation and win lines that stop at the last matching reel, roulette with the hover lattice and wheel spin, blackjack with vector-drawn suits, and a smooth crash curve. Sidebars pin their action block; leaving a live hand or round asks before forfeiting. The header balance holds the staked amount while the reels or wheel turn and only shows the payout when they stop. Refused spins cancel the animation. Live crash multipliers keep full precision for the chart; the terminal still displays two decimals. Verified live against a 4.2.0 server: register, login, auto-login, trust, all four games settling, history (50 rows), logout, disconnect, forfeit confirmation, and the version-mismatch screen. Release: 8.3 MB Linux, 6.8 MB Windows, 61 ms to window, 131 MB idle RSS.
Diffstat (limited to 'tests')
-rw-r--r--tests/client_core.rs67
1 files changed, 66 insertions, 1 deletions
diff --git a/tests/client_core.rs b/tests/client_core.rs
index 49abca2..2f43d47 100644
--- a/tests/client_core.rs
+++ b/tests/client_core.rs
@@ -17,7 +17,7 @@ use zagan_bet::client::games::roulette::{Cursor, Direction};
17use zagan_bet::client::ui::command_names; 17use zagan_bet::client::ui::command_names;
18use zagan_bet::client::view::{Command, RoulettePhase, SlotsPhase, View}; 18use zagan_bet::client::view::{Command, RoulettePhase, SlotsPhase, View};
19use zagan_bet::roulette::BetTarget; 19use zagan_bet::roulette::BetTarget;
20use zagan_bet::crash::CrashState; 20use zagan_bet::crash::{CrashState, multiplier_at};
21 21
22const WIN3: &str = "CCCCLLCLODGSDGS"; 22const WIN3: &str = "CCCCLLCLODGSDGS";
23const LOSS: &str = "CLOOGDSLCDCOGLS"; 23const LOSS: &str = "CLOOGDSLCDCOGLS";
@@ -538,6 +538,45 @@ fn info_shows_the_host_and_the_server_fields() {
538 assert!(h.screen.lines.iter().any(|line| line == "User: alice")); 538 assert!(h.screen.lines.iter().any(|line| line == "User: alice"));
539 assert!(h.screen.lines.iter().any(|line| line == "Account: 42")); 539 assert!(h.screen.lines.iter().any(|line| line == "Account: 42"));
540 assert!(h.screen.lines.iter().any(|line| line == "Balance: 1234 Kr")); 540 assert!(h.screen.lines.iter().any(|line| line == "Balance: 1234 Kr"));
541
542 let Some(View::Lobby(lobby)) = h.core.view() else {
543 panic!("the lobby view is always available");
544 };
545 assert_eq!(lobby.account.as_deref(), Some("42"));
546 assert_eq!(lobby.balance, Some(1234));
547}
548
549#[test]
550fn a_roulette_chip_can_be_taken_back_through_a_command() {
551 let mut h = Harness::new();
552 h.enter_roulette();
553 h.core.command(Command::SetChip(25));
554
555 h.core
556 .command(Command::PlaceBetAt(BetTarget::Straight { number: 17 }));
557 h.core
558 .command(Command::PlaceBetAt(BetTarget::Straight { number: 17 }));
559 let Some(View::Roulette(view)) = h.core.view() else {
560 panic!("roulette is open");
561 };
562 assert_eq!(view.bets.total(), 50);
563
564 h.core
565 .command(Command::RemoveBetAt(BetTarget::Straight { number: 17 }));
566 let Some(View::Roulette(view)) = h.core.view() else {
567 panic!("roulette is open");
568 };
569 assert_eq!(view.bets.total(), 25);
570 assert_eq!(view.phase, RoulettePhase::Placing);
571
572 h.core
573 .command(Command::RemoveBetAt(BetTarget::Straight { number: 17 }));
574 h.core
575 .command(Command::RemoveBetAt(BetTarget::Straight { number: 17 }));
576 let Some(View::Roulette(view)) = h.core.view() else {
577 panic!("roulette is open");
578 };
579 assert_eq!(view.bets.total(), 0);
541} 580}
542 581
543#[test] 582#[test]
@@ -1581,3 +1620,29 @@ fn login_requires_a_connection() {
1581 1620
1582 assert!(!h.sent.iter().any(|line| line.starts_with("AUTH"))); 1621 assert!(!h.sent.iter().any(|line| line.starts_with("AUTH")));
1583} 1622}
1623
1624#[test]
1625fn the_crash_multiplier_is_not_rounded_for_the_chart() {
1626 let mut h = Harness::new();
1627 h.enter_crash();
1628 h.key(Key::Char(' '));
1629 h.reply(&crash_line(
1630 "CRASH_START",
1631 &crash_state("running", 1.0, None, 0, 990),
1632 ));
1633
1634 h.tick(Duration::from_millis(1234));
1635 let expected = multiplier_at(Duration::from_millis(1234));
1636 let Some(View::Crash(view)) = h.core.view() else {
1637 panic!("expected a crash view");
1638 };
1639 assert!(
1640 (view.multiplier - expected).abs() < 1e-9,
1641 "the GUI chart needs the full precision value"
1642 );
1643 let rounded = (expected * 100.0).round() / 100.0;
1644 assert!(
1645 (view.multiplier - rounded).abs() > 1e-6,
1646 "a two-decimal store would flatten the curve into steps"
1647 );
1648}