//! Integration tests for CTRL-D / EOT behaviour. use galaxyui_core::integration::TestStep; use warp::integration_testing::step::new_step_with_default_assertions; use warp::integration_testing::terminal::util::current_shell_starter_and_version; use warp::integration_testing::terminal::{ assert_active_block_command_for_single_terminal_in_tab, assert_bootstrapping_stage, assert_no_block_executing, assert_terminal_bootstrapped, execute_python_interpreter_in_tab, wait_until_bootstrapped_single_pane_for_tab, PYTHON_PROMPT_READY, }; use warp::integration_testing::view_getters::assert_no_views_of_type; use warp::pane_group::PaneGroup; use warp::terminal::model::bootstrap::BootstrapStage; use warp::terminal::shell::ShellType; use warp::terminal::TerminalView; use warp::workspace::Workspace; use super::{new_builder, Builder}; use crate::util::write_all_rc_files_for_test; /// Verifies that ctrl-d correctly sends EOT to long-running commands. pub fn test_ctrl_d_eot() -> Builder { new_builder() .with_step(wait_until_bootstrapped_single_pane_for_tab(0)) .with_step(execute_python_interpreter_in_tab(0)) .with_step( new_step_with_default_assertions("Check ctrl-d terminates the command") .with_keystrokes(&["ctrl-d"]) .add_assertion(assert_no_block_executing(0, 0)), ) } // TODO(zheng) Add ctrl-d to exit the window too, after stopping this from beachballing. pub fn test_ctrl_d_exit() -> Builder { new_builder() .with_step(wait_until_bootstrapped_single_pane_for_tab(0)) .with_step( TestStep::new( "ctrl-d should exit the shell and the corresponding pane / tab should be closed", ) .with_keystrokes(&["ctrl-d"]) .add_assertion(assert_no_views_of_type::()) .add_assertion(assert_no_views_of_type::()) .add_assertion(assert_no_views_of_type::()), ) } /// Tests that CTRL-D will complete a blocking read during bootstrapping /// (e.g. omz update) by writing EOT to the PTY (which will result in an EOF condition). pub fn test_ctrl_d_handled_by_read_during_bootstrapping() -> Builder { new_builder() .set_should_run_test(|| { let (starter, _) = current_shell_starter_and_version(); // We need to fix https://github.com/warpdotdev/Warp/issues/1869 before // this test works on fish. !matches!(starter.shell_type(), ShellType::Fish) }) .with_setup(|utils| { let dir = utils.test_dir(); write_all_rc_files_for_test(dir, "python3"); }) .with_step( TestStep::new("Make sure shell is still bootstrapping") .add_assertion(assert_bootstrapping_stage(0, 0, BootstrapStage::ScriptExecution)) // When the client's RC files produce output, they appear in the command grid of the // active block. .add_assertion(assert_active_block_command_for_single_terminal_in_tab( &*PYTHON_PROMPT_READY, 0, )) ) .with_step( TestStep::new("ctrl-d should write EOT to PTY which should signal EOF to python and bootstrapping should finish") .with_keystrokes(&["ctrl-d"]) .add_assertion(assert_terminal_bootstrapped(0, 0)), ) } /// Tests that entering CTRL-D while the PTY is bootstrapping /// will exit the shell once bootstrapping is done /// (assuming nothing else consumed EOT during bootstrapping). pub fn test_ctrl_d_during_bootstrapping_exits_shell_upon_completion() -> Builder { let test = new_builder() .with_setup(|utils| { let dir = utils.test_dir(); write_all_rc_files_for_test(dir, "sleep 2"); }) .with_step( TestStep::new("Make sure shell is still bootstrapping").add_assertion( assert_bootstrapping_stage(0, 0, BootstrapStage::ScriptExecution), ), ); let final_test_step = TestStep::new("ctrl-d should write EOT to PTY which should exit the shell process") .with_keystrokes(&["ctrl-d"]); // On MacOS, the common behaviour for writing ctrl-d while bootstrapping // is to exit upon completion. // However, this differs on Linux where the common behaviour is to // ignore ctrl-d (and the corresponding EOF) while bootstrapping. let final_assertion = if cfg!(any(target_os = "linux", target_os = "freebsd")) { assert_terminal_bootstrapped(0, 0) } else { // TODO: figure out what the right behaviour is on windows. assert_no_views_of_type::() }; test.with_step(final_test_step.add_assertion(final_assertion)) }