#[allow(clippy::wildcard_imports)]
use super::super::*;
#[allow(clippy::wildcard_imports)]
use super::helpers::*;
use std::fs;
#[test]
fn filter_picker_options_are_derived_from_project_data() {
let (_tmp, app) = make_app_with_planning();
let options = |field: FilterField| app.filter_picker_options(field);
let ids = |field: FilterField| -> Vec<String> {
options(field).into_iter().map(|item| item.id).collect()
};
let columns = app.active_board_config().columns.clone();
assert_eq!(ids(FilterField::Status), columns);
let priorities = ids(FilterField::Priority);
for built_in in ["low", "medium", "high"] {
assert!(
priorities.contains(&built_in.to_string()),
"priority list must offer the built-in {built_in}: {priorities:?}"
);
}
let parent_id = app
.store
.list()
.unwrap()
.first()
.map(crate::id::canonical_ref)
.unwrap()
.to_string();
assert!(
ids(FilterField::Parent).contains(&parent_id),
"every stored issue is a candidate parent"
);
assert!(ids(FilterField::Cycle).contains(&"Cycle 1".to_string()));
assert!(ids(FilterField::Milestone).contains(&"GA".to_string()));
assert_eq!(
ids(FilterField::Category),
app.store.config.categories.order
);
}
#[test]
fn terminal_exit_reason_survives_the_wip_override_prompt() {
let (_tmp, mut app) = make_terminal_blocked_app();
{
let board = app
.store
.config
.kanban
.configurations
.get_mut("default")
.unwrap();
board.wip.limits.insert(
"todo".into(),
crate::wip::config::ColumnLimit::items(0, crate::wip::config::LimitPolicy::Block),
);
}
let _ = app.start_move(MoveTarget::Named("todo".into())).unwrap();
assert!(
matches!(app.mode, Mode::TransitionReason { .. }),
"leaving the terminal column asks for a reason, got {:?}",
app.mode
);
for c in "reopened".chars() {
let _ = app.handle_key(press(KeyCode::Char(c))).unwrap();
}
let _ = app.handle_key(press(KeyCode::Enter)).unwrap();
assert!(
matches!(app.mode, Mode::WipOverride { .. }),
"the blocking limit asks for its own reason next, got {:?}",
app.mode
);
for c in "capacity exception".chars() {
let _ = app.handle_key(press(KeyCode::Char(c))).unwrap();
}
let _ = app.handle_key(press(KeyCode::Enter)).unwrap();
assert!(matches!(app.mode, Mode::Board), "the move finishes");
let issue = app.store.get(IssueSelector::Number(2)).unwrap();
assert_eq!(issue.status.to_string(), "todo");
let path = app.store.config.issues_dir.join(&issue.filename);
let file = fs::read_to_string(path).unwrap();
assert!(
file.contains("reopened"),
"the transition reason survived the WIP prompt:
{file}"
);
assert!(
file.contains("capacity exception"),
"the WIP override reason was recorded too:
{file}"
);
}
#[test]
fn f2_inside_form_opens_the_picker_instead_of_triage() {
let (_tmp, mut app) = make_shell_app();
app.handle_key(press(KeyCode::Char('n'))).unwrap();
assert!(matches!(app.mode, Mode::Form));
assert_eq!(app.top_mode, TopMode::NewIssue);
app.form.as_mut().unwrap().focus = crate::ui::form::FormFocus::Labels;
app.handle_key(press(KeyCode::F(2))).unwrap();
assert!(matches!(app.mode, Mode::Form), "the form stays focused");
assert!(
app.form_picker.is_some(),
"F2 must still open the form picker"
);
assert_eq!(
app.top_mode,
TopMode::NewIssue,
"F2 must not have switched the shell to Triage"
);
}
#[test]
fn new_issue_target_triage_creates_into_the_entry_status() {
let (_tmp, mut app) = make_shell_app();
app.handle_key(press(KeyCode::F(1))).unwrap();
type_text(&mut app, "Inbox bound");
for _ in 0..12 {
app.handle_key(press(KeyCode::Down)).unwrap();
}
assert_eq!(
app.form.as_ref().unwrap().focus,
crate::ui::form::FormFocus::Target
);
app.handle_key(press(KeyCode::Enter)).unwrap();
let form = app.form.as_ref().unwrap();
assert_eq!(form.target, crate::ui::form::NewIssueTarget::Triage);
assert_eq!(
form.status, "triage",
"choosing Triage writes the inbox entry status"
);
app.handle_key(press(KeyCode::Down)).unwrap();
app.handle_key(press(KeyCode::Down)).unwrap();
assert_eq!(
app.form.as_ref().unwrap().focus,
crate::ui::form::FormFocus::Body
);
app.handle_key(press(KeyCode::Enter)).unwrap();
assert!(matches!(app.mode, Mode::Board));
let issue = app
.store
.list()
.unwrap()
.into_iter()
.find(|i| i.title == "Inbox bound")
.expect("the mode created the issue");
assert_eq!(issue.status.to_string(), "triage");
assert!(
issue.entered_at.is_some(),
"an issue created into the inbox carries the entry stamp the queue ages from"
);
}