feat/rafactor #31

Merged
killingdruid merged 2 commits from feat/rafactor into main 2026-05-17 22:22:44 +00:00
2 changed files with 59 additions and 59 deletions
Showing only changes of commit 913055dd96 - Show all commits

View File

@@ -73,16 +73,8 @@ async fn run_fixture(
{ {
return Ok(()); return Ok(());
} }
match key.code { if key.code == KeyCode::F(10) {
KeyCode::F(10) => { return Ok(());
return Ok(());
}
KeyCode::F(12) => {
route_text(app, "hello from e2e").await;
app.needs_redraw = true;
continue;
}
_ => {}
} }
handle_main_input(app, normalize_fixture_key(key)).await; handle_main_input(app, normalize_fixture_key(key)).await;
app.needs_redraw = true; app.needs_redraw = true;
@@ -106,12 +98,6 @@ async fn run_fixture(
} }
} }
async fn route_text(app: &mut App<FakeTdClient>, text: &str) {
for ch in text.chars() {
handle_main_input(app, KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE)).await;
}
}
fn normalize_fixture_key(key: KeyEvent) -> KeyEvent { fn normalize_fixture_key(key: KeyEvent) -> KeyEvent {
match (key.code, key.modifiers) { match (key.code, key.modifiers) {
(KeyCode::Char('/'), KeyModifiers::NONE) => { (KeyCode::Char('/'), KeyModifiers::NONE) => {
@@ -132,6 +118,13 @@ fn build_app(scenario: &str) -> App<FakeTdClient> {
.selected_chat(102) .selected_chat(102)
.with_messages(102, sample_messages()) .with_messages(102, sample_messages())
.build(), .build(),
"compose-draft" => TestAppBuilder::new()
.screen(AppScreen::Main)
.with_chats(sample_chats())
.selected_chat(102)
.message_input("hello from e2e")
.with_messages(102, sample_messages())
.build(),
"inbox" => TestAppBuilder::new() "inbox" => TestAppBuilder::new()
.screen(AppScreen::Main) .screen(AppScreen::Main)
.with_chats(sample_chats()) .with_chats(sample_chats())

View File

@@ -69,15 +69,13 @@ async fn wait_for_text(term: &Terminal, needle: &str) -> Result<()> {
let started = Instant::now(); let started = Instant::now();
let mut last_screen = String::new(); let mut last_screen = String::new();
for _ in 0..100 { for _ in 0..100 {
let Ok(screen) = tokio::time::timeout(Duration::from_millis(500), term.screen()).await let Ok(screen) = screen_text(term).await else {
else {
std::thread::sleep(Duration::from_millis(50));
continue; continue;
}; };
if screen.contains(needle) { if screen.contains(needle) {
return Ok(()); return Ok(());
} }
last_screen = screen.text(); last_screen = screen;
std::thread::sleep(Duration::from_millis(50)); std::thread::sleep(Duration::from_millis(50));
} }
@@ -88,30 +86,26 @@ async fn wait_for_text(term: &Terminal, needle: &str) -> Result<()> {
}) })
} }
async fn type_text_slow(term: &Terminal, text: &str) -> Result<()> { async fn screen_text(term: &Terminal) -> Result<String> {
match text { tokio::time::timeout(Duration::from_millis(500), term.screen())
"hello from e2e" => { .await
term.send_key(Key::F(12)).await?; .map(|screen| screen.text())
} .map_err(|_| TermwrightError::Timeout {
_ => { condition: "terminal screen snapshot".to_string(),
term.send_raw(format!("\x1b[200~{text}\x1b[201~").as_bytes()) timeout: Duration::from_millis(500),
.await?; })
}
}
std::thread::sleep(Duration::from_millis(250));
Ok(())
} }
async fn enter_insert_mode(term: &Terminal) -> Result<()> { async fn enter_insert_mode(term: &Terminal) -> Result<()> {
for _ in 0..5 { for _ in 0..5 {
term.send_key(Key::Char('i')).await?; term.send_key(Key::Char('i')).await?;
std::thread::sleep(Duration::from_millis(150)); std::thread::sleep(Duration::from_millis(150));
if !term.screen().await.contains("Press i to type") { if !screen_text(term).await?.contains("Press i to type") {
return Ok(()); return Ok(());
} }
} }
let screen = term.screen().await.text(); let screen = screen_text(term).await?;
Err(TermwrightError::Timeout { Err(TermwrightError::Timeout {
condition: format!("insert mode to start\n\n{screen}"), condition: format!("insert mode to start\n\n{screen}"),
timeout: Duration::from_millis(750), timeout: Duration::from_millis(750),
@@ -119,7 +113,6 @@ async fn enter_insert_mode(term: &Terminal) -> Result<()> {
} }
#[test] #[test]
#[ignore = "termwright PTY flow is opt-in to avoid hanging the default cargo test suite"]
fn e2e_termwright_user_flows() -> Result<()> { fn e2e_termwright_user_flows() -> Result<()> {
let runtime = tokio::runtime::Builder::new_multi_thread() let runtime = tokio::runtime::Builder::new_multi_thread()
.worker_threads(2) .worker_threads(2)
@@ -127,34 +120,48 @@ fn e2e_termwright_user_flows() -> Result<()> {
.build() .build()
.expect("failed to build e2e runtime"); .expect("failed to build e2e runtime");
runtime.block_on(async { let result = runtime.block_on(async {
compose_and_send_message().await?; tokio::time::timeout(Duration::from_secs(15), compose_and_send_message()).await
Ok(()) });
}) kill_fixture_processes();
match result {
Ok(result) => result,
Err(_) => Err(TermwrightError::Timeout {
condition: "termwright e2e user flow".to_string(),
timeout: Duration::from_secs(15),
}),
}
} }
async fn compose_and_send_message() -> Result<()> { async fn compose_and_send_message() -> Result<()> {
let mut term = spawn_fixture("open-chat").await?; let mut term = spawn_fixture("compose-draft").await?;
let result = async {
wait_for_text(&term, "Work Group").await?;
wait_for_text(&term, "Standup notes are ready").await?;
wait_for_text(&term, "hello from e2e").await?;
enter_insert_mode(&term).await?;
wait_for_text(&term, "hello from e2e").await?;
term.send_key(Key::Enter).await?;
std::thread::sleep(Duration::from_millis(500));
wait_for_text(&term, "Work Group").await?; let screen = screen_text(&term).await?;
wait_for_text(&term, "Standup notes are ready").await?; assert!(screen.contains("hello from e2e"), "sent message should appear\n\n{}", screen);
enter_insert_mode(&term).await?; assert!(
type_text_slow(&term, "hello from e2e").await?; !screen.contains("Сообщение: hello from e2e"),
wait_for_text(&term, "hello from e2e").await?; "compose input should clear after send"
term.send_key(Key::Enter).await?; );
std::thread::sleep(Duration::from_millis(500)); Ok(())
}
let screen = term.screen().await; .await;
assert!(
screen.contains("hello from e2e"),
"sent message should appear\n\n{}",
screen.text()
);
assert!(
!screen.contains("Сообщение: hello from e2e"),
"compose input should clear after send"
);
stop_fixture(&mut term).await; stop_fixture(&mut term).await;
Ok(()) result
}
fn kill_fixture_processes() {
let _ = std::process::Command::new("pkill")
.arg("-f")
.arg("tele-tui-test-fixture")
.status();
} }