terminal_test_context.rs

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