terminal_test_context.rs

 1use std::time::Duration;
 2
 3use alacritty_terminal::term::SizeInfo;
 4use gpui::{AppContext, ModelHandle, ReadModelWith, TestAppContext};
 5use itertools::Itertools;
 6
 7use crate::{
 8    connection::TerminalConnection, DEBUG_CELL_WIDTH, DEBUG_LINE_HEIGHT, DEBUG_TERMINAL_HEIGHT,
 9    DEBUG_TERMINAL_WIDTH,
10};
11
12pub struct TerminalTestContext<'a> {
13    pub cx: &'a mut TestAppContext,
14    pub connection: ModelHandle<TerminalConnection>,
15}
16
17impl<'a> TerminalTestContext<'a> {
18    pub fn new(cx: &'a mut TestAppContext) -> Self {
19        cx.set_condition_duration(Some(Duration::from_secs(5)));
20
21        let size_info = SizeInfo::new(
22            DEBUG_TERMINAL_WIDTH,
23            DEBUG_TERMINAL_HEIGHT,
24            DEBUG_CELL_WIDTH,
25            DEBUG_LINE_HEIGHT,
26            0.,
27            0.,
28            false,
29        );
30
31        let connection =
32            cx.add_model(|cx| TerminalConnection::new(None, None, None, size_info, cx));
33
34        TerminalTestContext { cx, connection }
35    }
36
37    pub async fn execute_and_wait<F>(&mut self, command: &str, f: F) -> String
38    where
39        F: Fn(String, &AppContext) -> bool,
40    {
41        let command = command.to_string();
42        self.connection.update(self.cx, |connection, _| {
43            connection.get_terminal().unwrap().write_to_pty(command);
44            connection
45                .get_terminal()
46                .unwrap()
47                .write_to_pty("\r".to_string());
48        });
49
50        self.connection
51            .condition(self.cx, |conn, cx| {
52                let content = Self::grid_as_str(conn);
53                f(content, cx)
54            })
55            .await;
56
57        self.cx
58            .read_model_with(&self.connection, &mut |conn, _: &AppContext| {
59                Self::grid_as_str(conn)
60            })
61    }
62
63    fn grid_as_str(connection: &TerminalConnection) -> String {
64        let grid = connection.get_terminal().unwrap().grid();
65        let lines = grid.display_iter().group_by(|i| i.point.line.0);
66        lines
67            .into_iter()
68            .map(|(_, line)| line.map(|i| i.c).collect::<String>())
69            .collect::<Vec<String>>()
70            .join("\n")
71    }
72}
73
74impl<'a> Drop for TerminalTestContext<'a> {
75    fn drop(&mut self) {
76        self.cx.set_condition_duration(None);
77    }
78}