From 0d89f657d5d690fff43e8eea34b780ef77f75519 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Sun, 3 Sep 2023 17:21:10 -0400 Subject: [PATCH] =?UTF-8?q?wip:=20Remove=20tests=20=F0=9F=9A=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.rs | 1079 +--------------------------------------------------- 1 file changed, 1 insertion(+), 1078 deletions(-) diff --git a/src/app.rs b/src/app.rs index 1cac750a..520966d3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3662,1081 +3662,4 @@ pub fn remove_tag(task: &mut Task, tag: &str) { } #[cfg(test)] -mod tests { - use std::{ffi::OsStr, fmt::Write, fs::File, io, path::Path}; - - use ratatui::{backend::TestBackend, buffer::Buffer}; - - use super::*; - - /// Returns a string representation of the given buffer for debugging purpose. - fn buffer_view(buffer: &Buffer) -> String { - let mut view = String::with_capacity(buffer.content.len() + buffer.area.height as usize * 3); - for cells in buffer.content.chunks(buffer.area.width as usize) { - let mut overwritten = vec![]; - let mut skip: usize = 0; - view.push('"'); - for (x, c) in cells.iter().enumerate() { - if skip == 0 { - view.push_str(&c.symbol); - } else { - overwritten.push((x, &c.symbol)) - } - skip = std::cmp::max(skip, c.symbol.width()).saturating_sub(1); - } - view.push('"'); - if !overwritten.is_empty() { - write!(&mut view, " Hidden by multi-width symbols: {:?}", overwritten).unwrap(); - } - view.push('\n'); - } - view - } - - #[test] - fn test_centered_rect() { - assert_eq!(centered_rect(50, 50, Rect::new(0, 0, 100, 100)), Rect::new(25, 25, 50, 50)); - } - - fn setup() { - use std::process::Stdio; - let mut f = File::open(Path::new(env!("TASKDATA")).parent().unwrap().join("export.json")).unwrap(); - let mut s = String::new(); - f.read_to_string(&mut s).unwrap(); - let tasks = task_hookrs::import::import(s.as_bytes()).unwrap(); - // tasks.iter_mut().find(| t | t.id().unwrap() == 1).unwrap().priority_mut().replace(&mut "H".to_string()); - // tasks.iter_mut().find(| t | t.id().unwrap() == 2).unwrap().priority_mut().replace(&mut "H".to_string()); - // tasks.iter_mut().find(| t | t.id().unwrap() == 4).unwrap().tags_mut().replace(&mut vec!["test".to_string(), "another tag".to_string()]); - assert!(task_hookrs::tw::save(&tasks).is_ok()); - } - - fn teardown() { - let cd = Path::new(env!("TASKDATA")); - std::fs::remove_dir_all(cd).unwrap(); - } - - async fn test_taskwarrior_tui_history() { - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - // setup(); - app.mode = Mode::Tasks(Action::Add); - app.update_completion_list(); - let input = "Wash car"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - app.handle_input(KeyCode::Right).await.unwrap(); - let input = " +test"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - app.handle_input(KeyCode::Char('\n')).await.unwrap(); - - app.mode = Mode::Tasks(Action::Add); - - app.update_completion_list(); - - let backend = TestBackend::new(50, 15); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - - let input = "Buy groceries"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - app.handle_input(KeyCode::Right).await.unwrap(); - let input = " +test"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - app.update(true).await.unwrap(); - app.handle_input(KeyCode::Down).await.unwrap(); - - assert_eq!("\"Buy groceries\" +test", app.command.value()); - - app.handle_input(KeyCode::Char('\n')).await.unwrap(); - - app.mode = Mode::Tasks(Action::Add); - app.update_completion_list(); - - let backend = TestBackend::new(50, 15); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - - let input = "Buy groceries"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - app.handle_input(KeyCode::Right).await.unwrap(); - app.handle_input(KeyCode::Backspace).await.unwrap(); - app.update(true).await.unwrap(); - app.handle_input(KeyCode::Down).await.unwrap(); - - assert_eq!("\"Buy groceries", app.command.value()); - - app.update(true).await.unwrap(); - - app.handle_input(KeyCode::Up).await.unwrap(); - - assert_eq!("\"Buy groceries\" +test", app.command.value()); - // teardown(); - } - - #[test] - fn test_taskwarrior_tui() { - let r = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap() - .block_on(async { _test_taskwarrior_tui().await }); - } - - async fn _test_taskwarrior_tui() { - let app = TaskwarriorTui::new("next", false).await.unwrap(); - - assert!( - app.task_by_index(0).is_none(), - "Expected task data to be empty but found {} tasks. Delete contents of {:?} and {:?} and run the tests again.", - app.tasks.len(), - Path::new(env!("TASKDATA")), - Path::new(env!("TASKDATA")).parent().unwrap().join(".config") - ); - - let app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app - .task_by_uuid(Uuid::parse_str("3f43831b-88dc-45e2-bf0d-4aea6db634cc").unwrap()) - .is_none()); - - test_draw_empty_task_report().await; - - test_draw_calendar().await; - test_draw_help_popup().await; - - setup(); - - let app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.task_by_index(0).is_some()); - - let app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app - .task_by_uuid(Uuid::parse_str("3f43831b-88dc-45e2-bf0d-4aea6db634cc").unwrap()) - .is_some()); - - test_draw_task_report_with_extended_modify_command().await; - // test_draw_task_report(); - test_task_tags().await; - test_task_style().await; - test_task_context().await; - test_task_tomorrow().await; - test_task_earlier_today().await; - test_task_later_today().await; - test_taskwarrior_tui_history().await; - - teardown(); - } - - async fn test_task_tags() { - // testing tags - let app = TaskwarriorTui::new("next", false).await.unwrap(); - let task = app.task_by_id(1).unwrap(); - - let tags = vec!["PENDING".to_string(), "PRIORITY".to_string()]; - - for tag in tags { - assert!(task.tags().unwrap().contains(&tag)); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - let task = app.task_by_id(11).unwrap(); - let tags = vec!["finance", "UNBLOCKED", "PENDING", "TAGGED", "UDA"] - .iter() - .map(ToString::to_string) - .collect::>(); - for tag in tags { - assert!(task.tags().unwrap().contains(&tag)); - } - - if let Some(task) = app.task_by_id(11) { - let i = app.task_index_by_uuid(*task.uuid()).unwrap_or_default(); - app.current_selection = i; - app.current_selection_id = None; - app.current_selection_uuid = None; - } - - app.task_quick_tag().unwrap(); - app.update(true).await.unwrap(); - - let task = app.task_by_id(11).unwrap(); - let tags = vec!["next", "finance", "UNBLOCKED", "PENDING", "TAGGED", "UDA"] - .iter() - .map(ToString::to_string) - .collect::>(); - for tag in tags { - assert!(task.tags().unwrap().contains(&tag)); - } - - app.task_quick_tag().unwrap(); - app.update(true).await.unwrap(); - - let task = app.task_by_id(11).unwrap(); - let tags = vec!["finance", "UNBLOCKED", "PENDING", "TAGGED", "UDA"] - .iter() - .map(ToString::to_string) - .collect::>(); - for tag in tags { - assert!(task.tags().unwrap().contains(&tag)); - } - } - - async fn test_task_style() { - let app = TaskwarriorTui::new("next", false).await.unwrap(); - let task = app.task_by_id(1).unwrap(); - for r in vec![ - "active", - "blocked", - "blocking", - "completed", - "deleted", - "due", - "due.today", - "keyword.", - "overdue", - "project.", - "recurring", - "scheduled", - "tag.", - "tagged", - "uda.", - ] { - assert!(app.config.rule_precedence_color.contains(&r.to_string())); - } - let style = app.style_for_task(&task); - - assert_eq!(style, Style::default().fg(Color::Indexed(2))); - - let task = app.task_by_id(11).unwrap(); - let style = app.style_for_task(&task); - } - - async fn test_task_context() { - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - assert!(app.update(true).await.is_ok()); - - app.context_select().unwrap(); - - assert_eq!(app.tasks.len(), 26); - assert_eq!(app.current_context_filter, ""); - - assert_eq!(app.contexts.table_state.current_selection(), Some(0)); - app.context_next(); - app.context_next(); - app.context_select().unwrap(); - assert_eq!(app.contexts.table_state.current_selection(), Some(2)); - - assert!(app.update(true).await.is_ok()); - - assert_eq!(app.tasks.len(), 1); - assert_eq!(app.current_context_filter, "+finance -private"); - - assert_eq!(app.contexts.table_state.current_selection(), Some(2)); - app.context_previous(); - app.context_previous(); - app.context_select().unwrap(); - assert_eq!(app.contexts.table_state.current_selection(), Some(0)); - - assert!(app.update(true).await.is_ok()); - - assert_eq!(app.tasks.len(), 26); - assert_eq!(app.current_context_filter, ""); - } - - async fn test_task_tomorrow() { - let total_tasks: u64 = 26; - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - let mut command = std::process::Command::new("task"); - command.arg("add"); - let tomorrow = now + chrono::Duration::days(1); - let message = format!( - "'new task for testing tomorrow' due:{:04}-{:02}-{:02}", - tomorrow.year(), - tomorrow.month(), - tomorrow.day(), - ); - - let shell = message.as_str().replace("'", "\\'"); - let cmd = shlex::split(&shell).unwrap(); - for s in cmd { - command.arg(&s); - } - let output = command.output().unwrap(); - let s = String::from_utf8_lossy(&output.stdout); - let re = Regex::new(r"^Created task (?P\d+).\n$").unwrap(); - let caps = re.captures(&s).unwrap(); - - let task_id = caps["task_id"].parse::().unwrap(); - assert_eq!(task_id, total_tasks + 1); - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), (total_tasks + 1) as usize); - assert_eq!(app.current_context_filter, ""); - - let task = app.task_by_id(task_id).unwrap(); - - for s in &["DUE", "MONTH", "PENDING", "QUARTER", "TOMORROW", "UDA", "UNBLOCKED", "YEAR"] { - if !(task.tags().unwrap().contains(&s.to_string())) { - println!("Expected {} to be in tags", s); - } - } - - let output = std::process::Command::new("task") - .arg("rc.confirmation=off") - .arg("undo") - .output() - .unwrap(); - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - } - - async fn test_task_earlier_today() { - let total_tasks: u64 = 26; - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - let mut command = std::process::Command::new("task"); - command.arg("add"); - let message = "'new task for testing earlier today' due:now"; - - let shell = message.replace("'", "\\'"); - let cmd = shlex::split(&shell).unwrap(); - for s in cmd { - command.arg(&s); - } - let output = command.output().unwrap(); - let s = String::from_utf8_lossy(&output.stdout); - let re = Regex::new(r"^Created task (?P\d+).\n$").unwrap(); - let caps = re.captures(&s).unwrap(); - let task_id = caps["task_id"].parse::().unwrap(); - assert_eq!(task_id, total_tasks + 1); - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), (total_tasks + 1) as usize); - assert_eq!(app.current_context_filter, ""); - - let task = app.task_by_id(task_id).unwrap(); - for s in &[ - "DUE", - "DUETODAY", - "MONTH", - "OVERDUE", - "PENDING", - "QUARTER", - "TODAY", - "UDA", - "UNBLOCKED", - "YEAR", - ] { - assert!(task.tags().unwrap().contains(&s.to_string())); - } - - let output = std::process::Command::new("task") - .arg("rc.confirmation=off") - .arg("undo") - .output() - .unwrap(); - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - } - - async fn test_task_later_today() { - let total_tasks: u64 = 26; - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - let mut command = std::process::Command::new("task"); - command.arg("add"); - let message = format!( - "'new task for testing later today' due:'{:04}-{:02}-{:02}T{:02}:{:02}:{:02}'", - now.year(), - now.month(), - now.day(), - now.hour(), - now.minute() + 1, - now.second(), - ); - - let shell = message.as_str().replace("'", "\\'"); - let cmd = shlex::split(&shell).unwrap(); - for s in cmd { - command.arg(&s); - } - let output = command.output().unwrap(); - let s = String::from_utf8_lossy(&output.stdout); - let re = Regex::new(r"^Created task (?P\d+).\n$").unwrap(); - let caps = re.captures(&s).unwrap(); - let task_id = caps["task_id"].parse::().unwrap(); - assert_eq!(task_id, total_tasks + 1); - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), (total_tasks + 1) as usize); - assert_eq!(app.current_context_filter, ""); - - let task = app.task_by_id(task_id).unwrap(); - for s in &["DUE", "DUETODAY", "MONTH", "PENDING", "QUARTER", "TODAY", "UDA", "UNBLOCKED", "YEAR"] { - assert!(task.tags().unwrap().contains(&s.to_string())); - } - - let output = std::process::Command::new("task") - .arg("rc.confirmation=off") - .arg("undo") - .output() - .unwrap(); - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - } - - async fn test_draw_empty_task_report() { - let mut expected = Buffer::with_lines(vec![ - " Tasks Projects Calendar [none]", - " ", - " ", - " ", - " ", - " ", - " ", - "──────────────────────────────────────────────────", - "Task not found ", - " ", - " ", - " ", - " ", - "Filter Tasks ", - "(status:pending or status:waiting) ", - ]); - - for i in 0..=49 { - // First line - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::REVERSED)); - } - for i in 1..=5 { - // Tasks - expected - .get_mut(i, 0) - .set_style(Style::default().add_modifier(Modifier::BOLD).add_modifier(Modifier::REVERSED)); - } - for i in 0..=49 { - // Command line - expected.get_mut(i, 13).set_style(Style::default().add_modifier(Modifier::REVERSED)); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - app.task_report_next(); - app.context_next(); - - let total_tasks: u64 = 0; - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - app.update(true).await.unwrap(); - - let backend = TestBackend::new(50, 15); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw(f); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected.area); - terminal.backend().assert_buffer(&expected); - } - - async fn test_draw_task_report_with_extended_modify_command() { - let mut expected1 = Buffer::with_lines(vec![ - "Modify Task 10 ", - " based on your .taskrc ", - " ", - ]); - - let mut expected2 = Buffer::with_lines(vec![ - "Modify Task 10 ", - "Support color for tasks b", - " ", - ]); - - for i in 0..=13 { - // Task - expected1.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::BOLD)); - expected2.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::BOLD)); - } - for i in 0..=24 { - // Command line - expected1.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::REVERSED)); - expected2.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::REVERSED)); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - let total_tasks: u64 = 26; - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - app.mode = Mode::Tasks(Action::Modify); - match app.task_table_state.mode() { - TableMode::SingleSelection => match app.task_current() { - Some(t) => { - let s = format!("{} ", t.description()); - app.modify = app.modify.with_value(s); - } - None => app.modify.reset(), - }, - TableMode::MultipleSelection => app.modify.reset(), - } - - app.update(true).await.unwrap(); - - let backend = TestBackend::new(25, 3); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - let rects = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Min(0), Constraint::Length(3)].as_ref()) - .split(f.size()); - - let position = &app.modify.visual_cursor(); - f.set_cursor( - std::cmp::min(rects[1].x + position as u16, rects[1].x + rects[1].width.saturating_sub(2)), - rects[1].y + 1, - ); - f.render_widget(Clear, rects[1]); - let selected = app.current_selection; - let task_ids = if app.tasks.is_empty() { - vec!["0".to_string()] - } else { - match app.task_table_state.mode() { - TableMode::SingleSelection => { - vec![app.tasks[selected].id().unwrap_or_default().to_string()] - } - TableMode::MultipleSelection => { - let mut tids = vec![]; - for uuid in app.marked.iter() { - if let Some(t) = app.task_by_uuid(*uuid) { - tids.push(t.id().unwrap_or_default().to_string()); - } - } - tids - } - } - }; - let label = if task_ids.len() > 1 { - format!("Modify Tasks {}", task_ids.join(",")) - } else { - format!("Modify Task {}", task_ids.join(",")) - }; - app.draw_command( - f, - rects[1], - app.modify.value(), - (Span::styled(label, Style::default().add_modifier(Modifier::BOLD)), None), - position, - true, - app.error.clone(), - ); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected1.area); - terminal.backend().assert_buffer(&expected1); - - app.modify.move_home(); - - terminal - .draw(|f| { - let rects = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Min(0), Constraint::Length(3)].as_ref()) - .split(f.size()); - - let position = &app.modify.visual_cursor(); - f.set_cursor( - std::cmp::min(rects[1].x + position as u16, rects[1].x + rects[1].width.saturating_sub(2)), - rects[1].y + 1, - ); - f.render_widget(Clear, rects[1]); - let selected = app.current_selection; - let task_ids = if app.tasks.is_empty() { - vec!["0".to_string()] - } else { - match app.task_table_state.mode() { - TableMode::SingleSelection => { - vec![app.tasks[selected].id().unwrap_or_default().to_string()] - } - TableMode::MultipleSelection => { - let mut tids = vec![]; - for uuid in app.marked.iter() { - if let Some(t) = app.task_by_uuid(*uuid) { - tids.push(t.id().unwrap_or_default().to_string()); - } - } - tids - } - } - }; - let label = if task_ids.len() > 1 { - format!("Modify Tasks {}", task_ids.join(",")) - } else { - format!("Modify Task {}", task_ids.join(",")) - }; - app.draw_command( - f, - rects[1], - app.modify.value(), - (Span::styled(label, Style::default().add_modifier(Modifier::BOLD)), None), - position, - true, - app.error.clone(), - ); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected2.area); - terminal.backend().assert_buffer(&expected2); - } - - async fn test_draw_task_report() { - let mut expected = Buffer::with_lines(vec![ - "╭Task|Calendar───────────────────────────────────╮", - "│ ID Age Deps P Projec Tag Due Descrip Urg │", - "│ │", - "│• 27 0s U new ta… 15.00│", - "│ 28 0s U none new ta… 15.00│", - "╰────────────────────────────────────────────────╯", - "╭Task 27─────────────────────────────────────────╮", - "│ │", - "│Name Value │", - "│------------- ----------------------------------│", - "│ID 27 │", - "╰────────────────────────────────────────────────╯", - "╭Filter Tasks────────────────────────────────────╮", - "│(status:pending or status:waiting) │", - "╰────────────────────────────────────────────────╯", - ]); - - for i in 1..=4 { - // Task - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::BOLD)); - } - for i in 6..=13 { - // Calendar - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::DIM)); - } - - for r in &[ - 1..=4, // ID - 6..=8, // Age - 10..=13, // Deps - 15..=15, // P - 17..=22, // Projec - 24..=30, // Tag - 32..=34, // Due - 36..=42, // Descr - 44..=48, // Urg - ] { - for i in r.clone() { - expected.get_mut(i, 1).set_style(Style::default().add_modifier(Modifier::UNDERLINED)); - } - } - - for i in 1..expected.area().width - 1 { - expected - .get_mut(i, 3) - .set_style(Style::default().fg(Color::Indexed(1)).bg(Color::Reset).add_modifier(Modifier::BOLD)); - } - - for i in 1..expected.area().width - 1 { - expected - .get_mut(i, 4) - .set_style(Style::default().fg(Color::Indexed(1)).bg(Color::Indexed(4))); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - app.task_report_next(); - app.context_next(); - - let total_tasks: u64 = 26; - - assert!(app.update(true).await.is_ok()); - assert_eq!(app.tasks.len(), total_tasks as usize); - assert_eq!(app.current_context_filter, ""); - - let now = Local::now(); - let now = TimeZone::from_utc_datetime(now.offset(), &now.naive_utc()); - - let mut command = std::process::Command::new("task"); - command.arg("add"); - let message = "'new task 1 for testing draw' priority:U"; - - let shell = message.replace("'", "\\'"); - let cmd = shlex::split(&shell).unwrap(); - for s in cmd { - command.arg(&s); - } - let output = command.output().unwrap(); - let s = String::from_utf8_lossy(&output.stdout); - let re = Regex::new(r"^Created task (?P\d+).\n$").unwrap(); - let caps = re.captures(&s).unwrap(); - let task_id = caps["task_id"].parse::().unwrap(); - assert_eq!(task_id, total_tasks + 1); - - let mut command = std::process::Command::new("task"); - command.arg("add"); - let message = "'new task 2 for testing draw' priority:U +none"; - - let shell = message.replace("'", "\\'"); - let cmd = shlex::split(&shell).unwrap(); - for s in cmd { - command.arg(&s); - } - let output = command.output().unwrap(); - let s = String::from_utf8_lossy(&output.stdout); - let re = Regex::new(r"^Created task (?P\d+).\n$").unwrap(); - let caps = re.captures(&s).unwrap(); - let task_id = caps["task_id"].parse::().unwrap(); - assert_eq!(task_id, total_tasks + 2); - - app.task_report_next(); - app.task_report_previous(); - app.task_report_next_page(); - app.task_report_previous_page(); - app.task_report_bottom(); - app.task_report_top(); - app.update(true).await.unwrap(); - - let backend = TestBackend::new(50, 15); - let mut terminal = Terminal::new(backend).unwrap(); - app.task_report_show_info = !app.task_report_show_info; - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - app.task_report_show_info = !app.task_report_show_info; - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - - let output = std::process::Command::new("task") - .arg("rc.confirmation=off") - .arg("undo") - .output() - .unwrap(); - let output = std::process::Command::new("task") - .arg("rc.confirmation=off") - .arg("undo") - .output() - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected.area); - terminal.backend().assert_buffer(&expected); - } - - async fn test_draw_calendar() { - let mut expected = Buffer::with_lines(vec![ - " Tasks Projects Calendar [none]", - " ", - " 2020 ", - " ", - " January February ", - " Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa ", - " 1 2 3 4 1 ", - " 5 6 7 8 9 10 11 2 3 4 5 6 7 8 ", - " 12 13 14 15 16 17 18 9 10 11 12 13 14 15 ", - " 19 20 21 22 23 24 25 16 17 18 19 20 21 22 ", - " 26 27 28 29 30 31 23 24 25 26 27 28 29 ", - " ", - " ", - " ", - " ", - ]); - - for i in 0..=49 { - // First line - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::REVERSED)); - } - for i in 20..=27 { - // Calendar - expected - .get_mut(i, 0) - .set_style(Style::default().add_modifier(Modifier::BOLD).add_modifier(Modifier::REVERSED)); - } - - for i in 0..=49 { - expected.get_mut(i, 2).set_style(Style::default().add_modifier(Modifier::UNDERLINED)); - } - - for i in 3..=22 { - expected.get_mut(i, 4).set_style(Style::default().bg(Color::Reset)); - } - - for i in 25..=44 { - expected.get_mut(i, 4).set_style(Style::default().bg(Color::Reset)); - } - - for i in 3..=22 { - expected - .get_mut(i, 5) - .set_style(Style::default().bg(Color::Reset).add_modifier(Modifier::UNDERLINED)); - } - - for i in 25..=44 { - expected - .get_mut(i, 5) - .set_style(Style::default().bg(Color::Reset).add_modifier(Modifier::UNDERLINED)); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - app.task_report_next(); - app.context_next(); - app.update(true).await.unwrap(); - - app.calendar_year = 2020; - app.mode = Mode::Calendar; - - app.update(true).await.unwrap(); - - let backend = TestBackend::new(50, 15); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected.area); - terminal.backend().assert_buffer(&expected); - } - - async fn test_draw_help_popup() { - let mut expected = Buffer::with_lines(vec![ - "╭Help──────────────────────────────────╮", - "│# Default Keybindings │", - "│ │", - "│Keybindings: │", - "│ │", - "│ Esc: │", - "│ │", - "│ ]: Next view │", - "│ │", - "│ [: Previous view │", - "╰──────────────────────────────────────╯", - "9% ─────────────────────────────────────", - ]); - - for i in 1..=4 { - // Calendar - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::BOLD)); - } - expected.get_mut(3, 11).set_style(Style::default().fg(Color::Gray)); - expected.get_mut(4, 11).set_style(Style::default().fg(Color::Gray)); - expected.get_mut(5, 11).set_style(Style::default().fg(Color::Gray)); - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - app.mode = Mode::Tasks(Action::HelpPopup); - app.task_report_next(); - app.context_next(); - app.update(true).await.unwrap(); - - let backend = TestBackend::new(40, 12); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw_help_popup(f, 100, 100); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected.area); - terminal.backend().assert_buffer(&expected); - } - - // #[test] - async fn test_draw_context_menu() { - let mut expected = Buffer::with_lines(vec![ - "╭Context───────────────────────────────────────────────────────────────────────╮", - "│Name Description Active│", - "│ │", - "│• none yes │", - "│ finance +finance -private no │", - "│ personal +personal -private no │", - "│ work -personal -private no │", - "│ │", - "│ │", - "╰──────────────────────────────────────────────────────────────────────────────╯", - ]); - - for i in 1..=7 { - // Task - expected.get_mut(i, 0).set_style(Style::default().add_modifier(Modifier::BOLD)); - } - - for i in 1..=10 { - // Task - expected.get_mut(i, 1).set_style(Style::default().add_modifier(Modifier::UNDERLINED)); - } - - for i in 12..=71 { - // Task - expected.get_mut(i, 1).set_style(Style::default().add_modifier(Modifier::UNDERLINED)); - } - - for i in 73..=78 { - // Task - expected.get_mut(i, 1).set_style(Style::default().add_modifier(Modifier::UNDERLINED)); - } - - for i in 1..=78 { - // Task - expected.get_mut(i, 3).set_style(Style::default().add_modifier(Modifier::BOLD)); - } - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - app.mode = Mode::Tasks(Action::ContextMenu); - app.task_report_next(); - app.update(true).await.unwrap(); - - let backend = TestBackend::new(80, 10); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw_context_menu(f, 100, 100); - app.draw_context_menu(f, 100, 100); - }) - .unwrap(); - - assert_eq!(terminal.backend().size().unwrap(), expected.area); - terminal.backend().assert_buffer(&expected); - } - - // #[test] - async fn test_graphemes() { - dbg!("写作业".graphemes(true).count()); - dbg!(UnicodeWidthStr::width("写作业")); - dbg!(UnicodeWidthStr::width("abc")); - - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - - if let Some(task) = app.task_by_id(27) { - let i = app.task_index_by_uuid(*task.uuid()).unwrap_or_default(); - app.current_selection = i; - app.current_selection_id = None; - app.current_selection_uuid = None; - } - app.update(true).await.unwrap(); - app.mode = Mode::Tasks(Action::Modify); - match app.task_current() { - Some(t) => { - let s = format!("{} ", t.description()); - app.modify = app.modify.with_value(s); - } - None => app.modify.reset(), - } - app.update(true).await.unwrap(); - - dbg!(app.modify.value()); - dbg!(app.modify.value().len()); - dbg!(app.modify.value().graphemes(true).count()); - dbg!(app.modify.cursor()); - let position = app.modify.visual_cursor(); - dbg!(position); - } - - // #[test] - async fn test_taskwarrior_tui_completion() { - let mut app = TaskwarriorTui::new("next", false).await.unwrap(); - app.handle_input(KeyCode::Char('z')).await.unwrap(); - app.mode = Mode::Tasks(Action::Add); - app.update_completion_list(); - let input = "Wash car"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - // app.handle_input(KeyCode::Ctrl('e')).await.unwrap(); - - let input = " project:CO"; - for c in input.chars() { - app.handle_input(KeyCode::Char(c)).await.unwrap(); - } - - app.mode = Mode::Tasks(Action::Add); - app.update_completion_list(); - app.handle_input(KeyCode::Tab).await.unwrap(); - app.handle_input(KeyCode::Char('\n')).await.unwrap(); - let backend = TestBackend::new(80, 50); - let mut terminal = Terminal::new(backend).unwrap(); - terminal - .draw(|f| { - app.draw(f); - app.draw(f); - }) - .unwrap(); - println!("{}", buffer_view(terminal.backend().buffer())); - } -} +mod tests {}