Skip to content

Commit e5ac26c

Browse files
committed
test: add alternate screen integration tests
Add tests simulating vim/vi behavior to verify: - Alternate screen shows only alternate content - Main screen content is restored on exit - Multiple enter/exit cycles work correctly - Scrollback history doesn't leak into alternate view
1 parent e712c11 commit e5ac26c

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

crates/tap-server/src/scrollback.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,129 @@ mod tests {
109109
assert!(!content.contains("\x1b[31m"));
110110
assert!(!content.contains("[31m"));
111111
}
112+
113+
// =========================================================================
114+
// Alternate screen integration tests (simulating vim/vi behavior)
115+
// =========================================================================
116+
117+
/// When entering alternate screen, only alternate content should be visible
118+
#[test]
119+
fn test_alternate_screen_shows_only_alternate_content() {
120+
let mut buf = ScrollbackBuffer::new();
121+
122+
// Write content to main screen
123+
buf.push(b"main line 1\r\nmain line 2\r\nmain line 3");
124+
125+
// Enter alternate screen (like vim does)
126+
buf.push(b"\x1b[?1049h");
127+
128+
// Write content to alternate screen
129+
buf.push(b"alternate content here");
130+
131+
// Should show ONLY alternate content, NOT main content
132+
let content = buf.get_lines(None);
133+
assert!(
134+
content.contains("alternate content here"),
135+
"should contain alternate content"
136+
);
137+
assert!(
138+
!content.contains("main line 1"),
139+
"should NOT contain main screen content when in alternate mode"
140+
);
141+
assert!(
142+
!content.contains("main line 2"),
143+
"should NOT contain main screen content when in alternate mode"
144+
);
145+
}
146+
147+
/// Simulates vim workflow: enter alternate, show file, exit, restore main
148+
#[test]
149+
fn test_vim_like_workflow() {
150+
let mut buf = ScrollbackBuffer::new();
151+
152+
// User types some commands in shell
153+
buf.push(b"$ ls -la\r\nfile1.txt\r\nfile2.txt\r\n$ vim file1.txt\r\n");
154+
155+
// Vim enters alternate screen
156+
buf.push(b"\x1b[?1049h");
157+
158+
// Vim shows file content (simplified)
159+
buf.push(b"Hello from file1.txt\r\nThis is vim editing mode");
160+
161+
// While in vim, should only see vim content
162+
let content_in_vim = buf.get_lines(None);
163+
assert!(content_in_vim.contains("Hello from file1.txt"));
164+
assert!(
165+
!content_in_vim.contains("$ ls -la"),
166+
"shell history should not be visible while in vim"
167+
);
168+
169+
// User exits vim (:q)
170+
buf.push(b"\x1b[?1049l");
171+
172+
// Back to main screen, should see original shell content
173+
let content_after_vim = buf.get_lines(None);
174+
assert!(
175+
content_after_vim.contains("$ ls -la"),
176+
"shell history should be restored after exiting vim"
177+
);
178+
assert!(
179+
content_after_vim.contains("file1.txt"),
180+
"ls output should be visible after exiting vim"
181+
);
182+
}
183+
184+
/// Test multiple alternate screen enter/exit cycles
185+
#[test]
186+
fn test_multiple_alternate_screen_cycles() {
187+
let mut buf = ScrollbackBuffer::new();
188+
189+
// Initial main screen content
190+
buf.push(b"session start\r\n");
191+
192+
for i in 1..=3 {
193+
// Enter alternate screen
194+
buf.push(b"\x1b[?1049h");
195+
buf.push(format!("editor session {i}").as_bytes());
196+
197+
// Should only see current editor session
198+
let in_alt = buf.get_lines(None);
199+
assert!(in_alt.contains(&format!("editor session {i}")));
200+
assert!(!in_alt.contains("session start"));
201+
202+
// Exit alternate screen
203+
buf.push(b"\x1b[?1049l");
204+
205+
// Should be back to main
206+
let in_main = buf.get_lines(None);
207+
assert!(in_main.contains("session start"));
208+
}
209+
}
210+
211+
/// Test that alternate screen content is isolated
212+
#[test]
213+
fn test_alternate_screen_isolation() {
214+
let mut buf = ScrollbackBuffer::new();
215+
216+
// Main screen has scrollback history
217+
for i in 1..=50 {
218+
buf.push(format!("history line {i}\r\n").as_bytes());
219+
}
220+
221+
// Enter alternate screen (TUI app)
222+
buf.push(b"\x1b[?1049h");
223+
buf.push(b"TUI application interface");
224+
225+
// Alt-e equivalent: get_lines should return ONLY the TUI content
226+
let content = buf.get_lines(None);
227+
assert!(content.contains("TUI application interface"));
228+
assert!(
229+
!content.contains("history line 1"),
230+
"scrollback history should not leak into alternate screen view"
231+
);
232+
assert!(
233+
!content.contains("history line 50"),
234+
"scrollback history should not leak into alternate screen view"
235+
);
236+
}
112237
}

0 commit comments

Comments
 (0)