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.write_to_pty(command);
44            connection.write_to_pty("\r".to_string());
45        });
46
47        self.connection
48            .condition(self.cx, |conn, cx| {
49                let content = Self::grid_as_str(conn);
50                f(content, cx)
51            })
52            .await;
53
54        self.cx
55            .read_model_with(&self.connection, &mut |conn, _: &AppContext| {
56                Self::grid_as_str(conn)
57            })
58    }
59
60    fn grid_as_str(connection: &TerminalConnection) -> String {
61        let term = connection.term.lock();
62        let grid_iterator = term.renderable_content().display_iter;
63        let lines = grid_iterator.group_by(|i| i.point.line.0);
64        lines
65            .into_iter()
66            .map(|(_, line)| line.map(|i| i.c).collect::<String>())
67            .collect::<Vec<String>>()
68            .join("\n")
69    }
70}
71
72impl<'a> Drop for TerminalTestContext<'a> {
73    fn drop(&mut self) {
74        self.cx.set_condition_duration(None);
75    }
76}