use crate::tui::plan::{PlanTask, TaskStatus, TaskType};
use crate::tui::render::plan_window::{VisibleWindow, current_task_index, pick_visible_window};
use uuid::Uuid;
fn task(order: usize, status: TaskStatus) -> PlanTask {
PlanTask {
id: Uuid::new_v4(),
order,
title: format!("Task #{order}"),
description: String::new(),
task_type: TaskType::Edit,
dependencies: Vec::new(),
complexity: 1,
acceptance_criteria: Vec::new(),
status,
notes: None,
completed_at: None,
retry_count: 0,
max_retries: 3,
artifacts: Vec::new(),
}
}
#[test]
fn anchor_is_first_in_progress_task() {
let tasks = vec![
task(1, TaskStatus::Completed),
task(2, TaskStatus::Completed),
task(3, TaskStatus::InProgress),
task(4, TaskStatus::Pending),
];
assert_eq!(current_task_index(&tasks), 2);
}
#[test]
fn anchor_falls_back_to_first_pending() {
let tasks = vec![
task(1, TaskStatus::Completed),
task(2, TaskStatus::Completed),
task(3, TaskStatus::Pending),
task(4, TaskStatus::Pending),
];
assert_eq!(current_task_index(&tasks), 2);
}
#[test]
fn anchor_falls_back_to_blocked_when_no_pending() {
let tasks = vec![
task(1, TaskStatus::Completed),
task(2, TaskStatus::Blocked("waiting on review".to_string())),
task(3, TaskStatus::Skipped),
];
assert_eq!(current_task_index(&tasks), 1);
}
#[test]
fn anchor_falls_back_to_failed_when_no_pending_or_blocked() {
let tasks = vec![
task(1, TaskStatus::Completed),
task(2, TaskStatus::Failed),
task(3, TaskStatus::Skipped),
];
assert_eq!(current_task_index(&tasks), 1);
}
#[test]
fn anchor_falls_back_to_last_when_everything_done() {
let tasks = vec![
task(1, TaskStatus::Completed),
task(2, TaskStatus::Skipped),
task(3, TaskStatus::Completed),
];
assert_eq!(current_task_index(&tasks), 2);
}
#[test]
fn anchor_index_on_empty_list_is_zero() {
let tasks: Vec<PlanTask> = Vec::new();
assert_eq!(current_task_index(&tasks), 0);
}
#[test]
fn in_progress_wins_even_when_a_later_task_is_pending() {
let tasks = vec![
task(1, TaskStatus::InProgress),
task(2, TaskStatus::Pending),
];
assert_eq!(current_task_index(&tasks), 0);
}
#[test]
fn empty_list_returns_zero_window() {
let w = pick_visible_window(0, 10, 0);
assert_eq!(w, VisibleWindow { start: 0, len: 0 });
}
#[test]
fn zero_available_rows_returns_zero_window() {
let w = pick_visible_window(5, 0, 2);
assert_eq!(w, VisibleWindow { start: 0, len: 0 });
}
#[test]
fn list_fitting_in_budget_renders_in_full() {
let w = pick_visible_window(7, 10, 3);
assert_eq!(w, VisibleWindow { start: 0, len: 7 });
}
#[test]
fn list_exactly_filling_budget_renders_in_full() {
let w = pick_visible_window(10, 10, 5);
assert_eq!(w, VisibleWindow { start: 0, len: 10 });
}
#[test]
fn overflowing_anchor_at_head_skips_above_indicator() {
let w = pick_visible_window(15, 10, 1);
assert_eq!(w.start, 0);
assert_eq!(w.len, 9);
}
#[test]
fn overflowing_anchor_at_tail_skips_below_indicator() {
let w = pick_visible_window(15, 10, 14);
assert_eq!(w.start + w.len, 15);
assert_eq!(w.len, 9);
}
#[test]
fn overflowing_anchor_in_middle_reserves_both_indicators() {
let w = pick_visible_window(15, 10, 7);
assert_eq!(w.len, 8);
assert!(w.start <= 7);
assert!(w.start + w.len > 7);
assert!(w.start >= 3 && w.start <= 4);
}
#[test]
fn overflowing_anchor_keeps_visible_when_near_head() {
let w = pick_visible_window(15, 10, 2);
assert_eq!(w.start, 0);
assert_eq!(w.len, 9);
assert!(w.start <= 2 && 2 < w.start + w.len);
}
#[test]
fn overflowing_anchor_keeps_visible_when_near_tail() {
let w = pick_visible_window(15, 10, 13);
assert!(w.start <= 13 && 13 < w.start + w.len);
assert_eq!(w.start + w.len, 15);
}
#[test]
fn tiny_budget_of_three_rows_still_renders_one_task() {
let w = pick_visible_window(10, 3, 5);
assert!(w.len >= 1);
assert!(w.start <= 5 && 5 < w.start + w.len);
}
#[test]
fn budget_of_one_row_anchor_in_middle() {
let w = pick_visible_window(10, 1, 5);
assert_eq!(w.len, 1);
assert_eq!(w.start, 5);
}
#[test]
fn overflowing_at_minimum_overflow_renders_correctly() {
let w = pick_visible_window(11, 10, 0);
assert_eq!(w.start, 0);
assert_eq!(w.len, 9);
}
#[test]
fn anchor_past_end_does_not_panic() {
let w = pick_visible_window(5, 10, 99);
assert!(w.len <= 5);
assert!(w.start + w.len <= 5);
}
#[test]
fn release_planning_screenshot_no_longer_truncates() {
let w = pick_visible_window(7, 10, 5);
assert_eq!(w, VisibleWindow { start: 0, len: 7 });
}