1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#[cfg(test)]
mod tests {
use std::env;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crate::appdata::WindowFocus;
use crate::keyboard::{handle_master_key, on_key_tree};
use crate::filesystem::get_string_abs_path;
/// Phase Red: Write a test that EXPOSES the bug
/// The bug: First press of tilde doesn't show home directory in UI
///
/// This test simulates the full render -> handle_events -> render loop
/// and verifies the rendered state is correct AFTER the first keypress
#[test]
fn test_render_state_after_first_tilde_press() {
// Setup: Initialize app at root directory
let mut app = crate::app::App::new();
app.starting_dir = "/".to_string();
app.init().expect("init failed");
app.window_focus = WindowFocus::Tree;
// === First draw (iteration 1, before any keypress) ===
// This is what the user sees BEFORE pressing tilde
let state_before = get_string_abs_path(&app.parent_file_nodes);
assert_eq!(state_before, "/", "initial state should be root");
// === Simulate key event handling ===
// This is what happens when user presses tilde
let key_event = KeyEvent::new(KeyCode::Char('~'), KeyModifiers::NONE);
// Step 1: handle_master_key should NOT catch tilde
let caught_by_master = handle_master_key(&mut app, key_event);
assert!(!caught_by_master, "tilde should NOT be caught by master_key");
// Step 2: on_key_tree should route to go_to_home
on_key_tree(&mut app, key_event);
// === Verify state AFTER key handling ===
// This is what the state SHOULD be after first press
let state_after_key = get_string_abs_path(&app.parent_file_nodes);
let home = env::var("HOME").expect("HOME not set");
// BUG EXPOSED HERE: If this assertion fails, the bug is in state management
assert!(
state_after_key.starts_with(&home) || state_after_key == home,
"BUG: After pressing tilde, state should be at home but was: {}",
state_after_key
);
// === Verify what render would display ===
// This simulates what the NEXT draw would show
let title_text = app.get_current_string_path();
// BUG EXPOSED HERE: If this assertion fails, the bug is in what render displays
assert!(
title_text.starts_with(&home) || title_text == home,
"BUG: Render would show {} but should show {}",
title_text,
home
);
// === Verify child nodes for render ===
// Render uses child_tree_nodes to build the file list
assert!(
!app.child_tree_nodes.is_empty(),
"BUG: child_tree_nodes should be populated for render"
);
println!("=== BUG TEST OUTPUT ===");
println!("Before tilde: {}", state_before);
println!("After tilde: {}", state_after_key);
println!("Render title: {}", title_text);
println!("Child nodes: {} items", app.child_tree_nodes.len());
}
/// Test that verifies the ENTIRE state is consistent for rendering
#[test]
fn test_render_consistency_after_navigation() {
let mut app = crate::app::App::new();
app.starting_dir = "/".to_string();
app.init().expect("init failed");
app.window_focus = WindowFocus::Tree;
// Press tilde to go home
let key_event = KeyEvent::new(KeyCode::Char('~'), KeyModifiers::NONE);
// Simulate full handle_events flow
if !handle_master_key(&mut app, key_event) {
on_key_tree(&mut app, key_event);
}
// Now verify EVERYTHING render needs is in sync
let path = get_string_abs_path(&app.parent_file_nodes);
let title = app.get_current_string_path();
let child_count = app.child_tree_nodes.len();
// All these should be consistent
assert_eq!(path, title, "parent_file_nodes and get_current_string_path should match");
assert!(child_count > 0, "child_tree_nodes should have items");
// The child_tree_nodes should be for the current directory
// This is what render_dir_tree uses
for node in &app.child_tree_nodes {
// Just verify we can render each node - this is what render does
let _ = node.render_list_item();
}
}
}