mod harness;
use harness::{ENTER, ESC, SHIFT_TAB, Terminal};
use std::time::Duration;
#[test]
fn shift_tab_cycles_every_safety_mode_in_the_footer() {
let mut term = Terminal::launch("pty-safety");
for expected in ["auto", "full_access", "plan", "read_only", "ask"] {
term.press(SHIFT_TAB);
assert!(
term.wait_for_text(&format!("safety: {expected}"), Duration::from_secs(10)),
"Shift+Tab should have reached {expected}. Screen:\n{}",
term.frame_text(),
);
}
let screen = term.frame_text().to_lowercase();
assert!(
!screen.contains("restores:"),
"the footer still names a restore target:\n{}",
term.frame_text()
);
assert!(
!screen.contains("alt+p"),
"the footer still advertises Alt+P:\n{}",
term.frame_text()
);
}
#[cfg(windows)]
#[test]
fn ctrl_v_attaches_a_png_only_clipboard() {
const CTRL_V: &[u8] = &[0x16];
let png = std::env::temp_dir().join("mermaid-pty-visual-probe.png");
let arm = format!(
"\
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$bmp = New-Object System.Drawing.Bitmap 120, 80
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.Clear([System.Drawing.Color]::Teal)
$g.Dispose()
$bmp.Save('{png}', [System.Drawing.Imaging.ImageFormat]::Png)
$ms = New-Object System.IO.MemoryStream(,[System.IO.File]::ReadAllBytes('{png}'))
$d = New-Object System.Windows.Forms.DataObject
$d.SetData('PNG', $false, $ms)
[System.Windows.Forms.Clipboard]::SetDataObject($d, $true)
if ([System.Windows.Forms.Clipboard]::ContainsImage()) {{ throw 'expected a PNG-only clipboard' }}",
png = png.display(),
);
let armed = std::process::Command::new("powershell")
.args(["-NoProfile", "-STA", "-Command", &arm])
.output()
.expect("run the clipboard arming script");
assert!(
armed.status.success(),
"could not arm a PNG-only clipboard: {}",
String::from_utf8_lossy(&armed.stderr)
);
let mut term = Terminal::launch("pty-paste");
term.press(CTRL_V);
let landed = term.wait_for_text("[Image #1]", Duration::from_secs(30));
let _ = std::fs::remove_file(&png);
assert!(
landed,
"Ctrl+V did not attach the image. Screen:\n{}",
term.frame_text()
);
}
#[test]
fn slash_model_opens_a_picker_and_escape_dismisses_it() {
let mut term = Terminal::launch("pty-model");
term.type_text("/model");
term.press(ENTER);
assert!(
term.wait_for_text("Select model", Duration::from_secs(20)),
"/model did not open a picker. Screen:\n{}",
term.frame_text()
);
for hint in ["Enter switch", "type to filter", "Esc cancel"] {
assert!(
term.wait_for_text(hint, Duration::from_secs(5)),
"the picker must advertise {hint:?}. Screen:\n{}",
term.frame_text()
);
}
term.press(ESC);
assert!(
term.wait_for_gone("Select model", Duration::from_secs(5)),
"Esc did not dismiss the picker. Screen:\n{}",
term.frame_text()
);
}