返回 CodeWhale
work_bar_keys_pty.rs
根目录 / crates / tui / tests / cucumber / work_bar_keys_pty.rs
1 //! Press the advertised work-bar chord through a real terminal decoder,
2 //! including the fresh-session screen where the hint first appears.
3
4 use std::time::Duration;
5
6 use super::qa_harness::{
7 harness::{Harness, make_sealed_workspace},
8 keys,
9 };
10
11 #[test]
12 fn work_bar_opens_from_launch_with_legacy_and_enhanced_keys() {
13 for (rows, cols) in [(12, 40), (16, 60), (24, 80), (32, 100), (40, 140)] {
14 let workspace = make_sealed_workspace().expect("sealed workspace");
15 std::fs::write(workspace.home().join(".codewhale/.onboarded"), "").unwrap();
16 let trust = workspace.workspace().join(".deepseek");
17 std::fs::create_dir_all(&trust).unwrap();
18 std::fs::write(trust.join("trusted"), "").unwrap();
19 let mut tui = Harness::builder(Harness::cargo_bin("codewhale-tui"))
20 .cwd(workspace.workspace())
21 .clear_env()
22 .seal_home(workspace.home())
23 .env("CODEWHALE_DISABLE_MODELS_DEV_FETCH", "1")
24 .env("CODEWHALE_NO_UPDATE_CHECK", "1")
25 .env("NO_ANIMATIONS", "1")
26 .env("RUST_LOG", "warn")
27 .args([
28 "--workspace",
29 workspace.workspace().to_str().unwrap(),
30 "--no-project-config",
31 "--mouse-capture",
32 ])
33 .size(rows, cols)
34 .spawn()
35 .expect("start TUI");
36 tui.wait_for_text("Choose your model provider", Duration::from_secs(15))
37 .unwrap();
38 tui.send(keys::key::ctrl('o')).unwrap();
39 tui.wait_for_text("You're ready.", Duration::from_secs(5))
40 .unwrap();
41 tui.send(keys::key::enter()).unwrap();
42 tui.wait_for_text("New session", Duration::from_secs(15))
43 .unwrap();
44 tui.wait_for_idle(Duration::from_millis(250), Duration::from_secs(5))
45 .unwrap();
46
47 super::launch_card_pty::capture(&mut tui, "workbar-closed");
48
49 // Legacy Ctrl+] is one byte, decoded by crossterm as Ctrl+5.
50 tui.send([0x1d]).unwrap();
51 tui.wait_for_text("no agents have run this session", Duration::from_secs(5))
52 .unwrap_or_else(|error| panic!("{cols}x{rows}: legacy Ctrl+] failed: {error}"));
53
54 super::launch_card_pty::capture(&mut tui, "workbar-fleet");
55
56 // The enhanced backward chord must work on the same launch screen.
57 tui.send(b"\x1b[9;6u").unwrap();
58 tui.wait_for_text("no to-dos yet", Duration::from_secs(5))
59 .unwrap();
60 super::launch_card_pty::capture(&mut tui, "workbar-tasks");
61 // The visible close control and keyboard Escape share the close action.
62 let (row, col) = tui.frame().find_text("×").expect("visible close control");
63 tui.send(keys::mouse::click(row, col)).unwrap();
64 tui.wait_for(
65 |frame| !frame.contains("no to-dos yet"),
66 Duration::from_secs(5),
67 )
68 .unwrap();
69
70 tui.send(b"\x1b[93;5u").unwrap();
71 tui.wait_for_text("no agents have run this session", Duration::from_secs(5))
72 .unwrap_or_else(|error| panic!("{cols}x{rows}: enhanced Ctrl+] failed: {error}"));
73
74 // Ordinary bracket/digit text still reaches the composer; the legacy
75 // chord also works after typing has dismissed the launch card.
76 tui.send("draft ]5").unwrap();
77 tui.wait_for_text("draft ]5", Duration::from_secs(5))
78 .unwrap();
79 tui.wait_for_idle(Duration::from_millis(250), Duration::from_secs(5))
80 .unwrap();
81 tui.send([0x1d]).unwrap();
82 tui.wait_for_text("nothing running in the background", Duration::from_secs(5))
83 .unwrap();
84 tui.shutdown();
85 }
86 }
87
87 lines RUST