Stabilize termwright e2e flow
This commit is contained in:
@@ -73,16 +73,8 @@ async fn run_fixture(
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
match key.code {
|
||||
KeyCode::F(10) => {
|
||||
return Ok(());
|
||||
}
|
||||
KeyCode::F(12) => {
|
||||
route_text(app, "hello from e2e").await;
|
||||
app.needs_redraw = true;
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
if key.code == KeyCode::F(10) {
|
||||
return Ok(());
|
||||
}
|
||||
handle_main_input(app, normalize_fixture_key(key)).await;
|
||||
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 {
|
||||
match (key.code, key.modifiers) {
|
||||
(KeyCode::Char('/'), KeyModifiers::NONE) => {
|
||||
@@ -132,6 +118,13 @@ fn build_app(scenario: &str) -> App<FakeTdClient> {
|
||||
.selected_chat(102)
|
||||
.with_messages(102, sample_messages())
|
||||
.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()
|
||||
.screen(AppScreen::Main)
|
||||
.with_chats(sample_chats())
|
||||
|
||||
@@ -69,15 +69,13 @@ async fn wait_for_text(term: &Terminal, needle: &str) -> Result<()> {
|
||||
let started = Instant::now();
|
||||
let mut last_screen = String::new();
|
||||
for _ in 0..100 {
|
||||
let Ok(screen) = tokio::time::timeout(Duration::from_millis(500), term.screen()).await
|
||||
else {
|
||||
std::thread::sleep(Duration::from_millis(50));
|
||||
let Ok(screen) = screen_text(term).await else {
|
||||
continue;
|
||||
};
|
||||
if screen.contains(needle) {
|
||||
return Ok(());
|
||||
}
|
||||
last_screen = screen.text();
|
||||
last_screen = screen;
|
||||
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<()> {
|
||||
match text {
|
||||
"hello from e2e" => {
|
||||
term.send_key(Key::F(12)).await?;
|
||||
}
|
||||
_ => {
|
||||
term.send_raw(format!("\x1b[200~{text}\x1b[201~").as_bytes())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(250));
|
||||
Ok(())
|
||||
async fn screen_text(term: &Terminal) -> Result<String> {
|
||||
tokio::time::timeout(Duration::from_millis(500), term.screen())
|
||||
.await
|
||||
.map(|screen| screen.text())
|
||||
.map_err(|_| TermwrightError::Timeout {
|
||||
condition: "terminal screen snapshot".to_string(),
|
||||
timeout: Duration::from_millis(500),
|
||||
})
|
||||
}
|
||||
|
||||
async fn enter_insert_mode(term: &Terminal) -> Result<()> {
|
||||
for _ in 0..5 {
|
||||
term.send_key(Key::Char('i')).await?;
|
||||
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(());
|
||||
}
|
||||
}
|
||||
|
||||
let screen = term.screen().await.text();
|
||||
let screen = screen_text(term).await?;
|
||||
Err(TermwrightError::Timeout {
|
||||
condition: format!("insert mode to start\n\n{screen}"),
|
||||
timeout: Duration::from_millis(750),
|
||||
@@ -119,7 +113,6 @@ async fn enter_insert_mode(term: &Terminal) -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "termwright PTY flow is opt-in to avoid hanging the default cargo test suite"]
|
||||
fn e2e_termwright_user_flows() -> Result<()> {
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(2)
|
||||
@@ -127,34 +120,48 @@ fn e2e_termwright_user_flows() -> Result<()> {
|
||||
.build()
|
||||
.expect("failed to build e2e runtime");
|
||||
|
||||
runtime.block_on(async {
|
||||
compose_and_send_message().await?;
|
||||
Ok(())
|
||||
})
|
||||
let result = runtime.block_on(async {
|
||||
tokio::time::timeout(Duration::from_secs(15), compose_and_send_message()).await
|
||||
});
|
||||
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<()> {
|
||||
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?;
|
||||
wait_for_text(&term, "Standup notes are ready").await?;
|
||||
enter_insert_mode(&term).await?;
|
||||
type_text_slow(&term, "hello from e2e").await?;
|
||||
wait_for_text(&term, "hello from e2e").await?;
|
||||
term.send_key(Key::Enter).await?;
|
||||
std::thread::sleep(Duration::from_millis(500));
|
||||
|
||||
let screen = term.screen().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"
|
||||
);
|
||||
let screen = screen_text(&term).await?;
|
||||
assert!(screen.contains("hello from e2e"), "sent message should appear\n\n{}", screen);
|
||||
assert!(
|
||||
!screen.contains("Сообщение: hello from e2e"),
|
||||
"compose input should clear after send"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
.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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user