#![cfg(feature = "plugins")]
use crate::common::harness::{copy_plugin, copy_plugin_lib, EditorTestHarness};
use crossterm::event::{KeyCode, KeyModifiers};
use fresh::services::plugins::api::{ActionPopupAction, PluginCommand};
use fresh::view::ui::status_bar::RemoteIndicatorOverride;
use std::fs;
fn set_up_workspace() -> (tempfile::TempDir, std::path::PathBuf) {
fresh::i18n::set_locale("en");
let temp = tempfile::tempdir().unwrap();
let workspace = temp.path().to_path_buf();
let dc = workspace.join(".devcontainer");
fs::create_dir_all(&dc).unwrap();
fs::write(
dc.join("devcontainer.json"),
r#"{ "name": "fake", "image": "ubuntu:22.04" }"#,
)
.unwrap();
let plugins_dir = workspace.join("plugins");
fs::create_dir_all(&plugins_dir).unwrap();
copy_plugin_lib(&plugins_dir);
copy_plugin(&plugins_dir, "devcontainer");
(temp, workspace)
}
fn assert_devcontainer_plugin_ready(harness: &EditorTestHarness) {
let plugins = harness.editor().plugin_manager().list_plugins();
let loaded: Vec<_> = plugins.iter().map(|p| p.name.clone()).collect();
assert!(
plugins.iter().any(|p| p.name == "devcontainer"),
"`devcontainer` plugin must be loaded before driving its \
commands. Loaded plugins: {:?}",
loaded,
);
}
fn show_failed_attach_popup(harness: &mut EditorTestHarness) {
harness
.editor_mut()
.handle_plugin_command(PluginCommand::ShowActionPopup {
popup_id: "devcontainer-failed-attach".to_string(),
title: "Dev Container Attach Failed".to_string(),
message: "Dev container attach failed: exit 1".to_string(),
actions: vec![
ActionPopupAction {
id: "retry".to_string(),
label: "Retry".to_string(),
},
ActionPopupAction {
id: "show_build_logs".to_string(),
label: "Show Build Logs".to_string(),
},
ActionPopupAction {
id: "reopen_local".to_string(),
label: "Reopen Locally".to_string(),
},
ActionPopupAction {
id: "dismiss".to_string(),
label: "Dismiss (ESC)".to_string(),
},
],
})
.unwrap();
}
#[test]
fn devcontainer_failed_attach_popup_has_four_action_rows() {
let (_temp, workspace) = set_up_workspace();
let mut harness = EditorTestHarness::with_working_dir(140, 40, workspace).unwrap();
harness.tick_and_render().unwrap();
assert_devcontainer_plugin_ready(&harness);
show_failed_attach_popup(&mut harness);
harness.render().unwrap();
let screen = harness.screen_to_string();
for label in [
"Dev Container Attach Failed",
"Retry",
"Show Build Logs",
"Reopen Locally",
"Dismiss",
] {
assert!(
screen.contains(label),
"Failed-attach popup must render '{}'. Screen:\n{}",
label,
screen,
);
}
}
#[test]
fn devcontainer_failed_attach_popup_reopen_local_clears_override() {
let (_temp, workspace) = set_up_workspace();
let mut harness = EditorTestHarness::with_working_dir(140, 40, workspace).unwrap();
harness.tick_and_render().unwrap();
assert_devcontainer_plugin_ready(&harness);
harness.editor_mut().remote_indicator_override = Some(RemoteIndicatorOverride::FailedAttach {
error: Some("exit 1".into()),
});
show_failed_attach_popup(&mut harness);
harness.render().unwrap();
assert!(
matches!(
harness.editor().remote_indicator_override,
Some(RemoteIndicatorOverride::FailedAttach { .. })
),
"Precondition: FailedAttach override must be set"
);
harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
harness.send_key(KeyCode::Down, KeyModifiers::NONE).unwrap();
harness
.send_key(KeyCode::Enter, KeyModifiers::NONE)
.unwrap();
harness
.wait_until(|h| h.editor().remote_indicator_override.is_none())
.unwrap();
}