157 lines · 6.8 KB · Rust
RawDownload
use std::time::Duration; use regex::Regex;use warpui::integration::{AssertionOutcome, TestStep};use warpui::{async_assert, async_assert_eq}; use super::util::{remote_server_ssh_command, remote_server_user_host, ssh_command, user_host};use crate::integration_testing::step::assert_no_pending_model_events;use crate::integration_testing::terminal::util::ExpectedExitStatus;use crate::integration_testing::terminal::{    assert_long_running_block_executing_for_single_terminal_in_tab,    execute_command_for_single_terminal_in_tab, validate_block_output,    wait_until_bootstrapped_pane,};use crate::integration_testing::view_getters::{single_terminal_view, terminal_view};use crate::terminal::model::rich_content::RichContentType;use crate::terminal::view::WithinBlockBanner; /// Sets environment variables needed by the Google Cloud SDK.pub fn setup_gcloud_sdk() -> TestStep {    execute_command_for_single_terminal_in_tab(        0,        "export CLOUDSDK_CONFIG=\"$ORIGINAL_HOME/.config/gcloud\"".into(),        ExpectedExitStatus::Success,        (),    )} /// Initiates an SSH connection, executing the necessary command and then/// waiting briefly (to avoid any subsequent steps performing assertions about/// long-running command state faster than the ssh command can fail).pub fn enter_ssh_command(shell: &str) -> TestStep {    let ssh_command = ssh_command(shell, true);    TestStep::new(&format!("Start ssh connection with remote shell '{shell}'"))        .with_typed_characters(&[&ssh_command])        .with_keystrokes(&["enter"])        .set_post_step_pause(Duration::from_millis(250))}pub fn enter_remote_server_ssh_command(shell: &str) -> TestStep {    let ssh_command = remote_server_ssh_command(shell, true);    TestStep::new(&format!(        "Start remote-server ssh connection with remote shell '{shell}'"    ))    .with_typed_characters(&[&ssh_command])    .with_keystrokes(&["enter"])    .set_post_step_pause(Duration::from_millis(250))} pub fn enter_remote_subshell_command(shell: &str) -> TestStep {    let ssh_command = ssh_command(shell, false);    TestStep::new(&format!("Start ssh connection with remote shell '{shell}'"))        .with_typed_characters(&[&ssh_command])        .with_keystrokes(&["enter"])        .set_post_step_pause(Duration::from_millis(250))} /// Waits for a password prompt.pub fn wait_for_password_prompt(tab_index: usize, shell: &str) -> TestStep {    let user_host = user_host(shell);    wait_for_password_prompt_for_user_host(tab_index, user_host)} pub fn wait_for_remote_server_password_prompt(tab_index: usize, shell: &str) -> TestStep {    let user_host = remote_server_user_host(shell);    wait_for_password_prompt_for_user_host(tab_index, user_host)} fn wait_for_password_prompt_for_user_host(tab_index: usize, user_host: String) -> TestStep {    let regex = Regex::new(&format!("{user_host}'s password:[\\s]*$"))        .expect("regex should not fail to compile");    TestStep::new("Wait for password prompt")        // Wait up to 40 seconds for the password prompt to appear.  This is        // intended to reduce flakiness due to still-not-understood delays        // in the password prompt appearing.        .set_timeout(Duration::from_secs(40))        .add_assertion(assert_long_running_block_executing_for_single_terminal_in_tab(true, 0))        .add_assertion(move |app, window_id| {            validate_block_output(&regex, tab_index, 0, window_id, app)        })} /// Enters the password for the user in the SSH testing VM.pub fn enter_ssh_password() -> TestStep {    TestStep::new("Enter ssh password").with_typed_characters(&["password\n"])} pub fn enter_local_subshell_command(shell: &str) -> TestStep {    TestStep::new(&format!("Enter local subshell command for {shell}"))        .with_input_string(shell, Some(&["enter"]))        // Wait for shell line editor to become active before moving to next test step.        .set_post_step_pause(Duration::from_millis(50))} pub fn assert_subshell_banner_is_showing() -> TestStep {    TestStep::new("Assert the Warpify banner is visible")        .add_assertion(move |app, window_id| {            let terminal_view = single_terminal_view(app, window_id);            terminal_view.read(app, |view, _ctx| {                async_assert!(matches!(                    view.model                        .lock()                        .block_list_mut()                        .active_block()                        .block_banner(),                    Some(WithinBlockBanner::WarpifyBanner(..))                ))            })        })        // Wait for outstanding model events to finish before moving to the next step        .add_named_assertion("no pending model events", assert_no_pending_model_events())        .set_post_step_pause(Duration::from_millis(50))} pub fn trigger_subshell_bootstrap() -> TestStep {    TestStep::new("Trigger subshell bootstrap").with_keystrokes(&["ctrl-i"])} pub fn assert_subshell_is_bootstrapped(tab_index: usize, pane_index: usize) -> TestStep {    wait_until_bootstrapped_pane(tab_index, pane_index).add_named_assertion(        "Subshell info block was displayed and no extraneous blocks added",        move |app, window_id| {            let terminal_view = terminal_view(app, window_id, tab_index, pane_index);            terminal_view.read(app, |view, _ctx| {                let model = view.model.lock();                 let Some((success_block_index, rich_content_type)) = model                    .block_list()                    .last_non_hidden_rich_content_block_after_block(None)                    .map(|(success_block_index, block)| (success_block_index, block.content_type))                else {                    return AssertionOutcome::failure("No rich content block found!".to_owned());                };                 match rich_content_type {                    Some(RichContentType::WarpifySuccessBlock) => {}                    _ => {                        return AssertionOutcome::failure(                            "Warpify success block wasn't added to the blocklist".to_owned(),                        );                    }                }                 let success_block_index: usize = success_block_index.into();                // Make sure there are no non-in-band-generator blocks added to the blocklist in                // between the static block and the active block (which is not yet finished).                async_assert_eq!(                    model.block_list().blocks()[success_block_index + 1..]                        .iter()                        .filter(|block| !block.is_in_band_command_block() && block.finished())                        .count(),                    0,                    "Added extraneous blocks to the block list.",                )            })        },    )}