feat(board): show upcoming deadline tasks
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
using TaskTracker.Api.Pages;
|
||||
using TaskTracker.Core.Entities;
|
||||
using TaskTracker.Core.Enums;
|
||||
using Xunit;
|
||||
|
||||
namespace TaskTracker.Tests;
|
||||
|
||||
public class BoardUpcomingTasksTests
|
||||
{
|
||||
[Fact]
|
||||
public void SelectUpcomingTasks_excludes_completed_abandoned_and_tasks_without_a_deadline()
|
||||
{
|
||||
var dueAt = DateTimeOffset.Parse("2026-08-14T09:00:00Z");
|
||||
var tasks = new[]
|
||||
{
|
||||
Task("pending", WorkTaskStatus.Pending, dueAt),
|
||||
Task("completed", WorkTaskStatus.Completed, dueAt.AddHours(-1)),
|
||||
Task("abandoned", WorkTaskStatus.Abandoned, dueAt.AddHours(1)),
|
||||
Task("no deadline", WorkTaskStatus.Active),
|
||||
};
|
||||
|
||||
var upcoming = BoardModel.SelectUpcomingTasks(tasks, category: null, hasSubtasks: false);
|
||||
|
||||
var task = Assert.Single(upcoming);
|
||||
Assert.Equal("pending", task.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectUpcomingTasks_includes_top_level_tasks_and_subtasks_in_due_date_order()
|
||||
{
|
||||
var parent = Task("top level", WorkTaskStatus.Pending, DateTimeOffset.Parse("2026-08-14T12:00:00Z"));
|
||||
var subtask = Task("subtask", WorkTaskStatus.Active, DateTimeOffset.Parse("2026-08-14T10:00:00Z"), parentTaskId: 1);
|
||||
var later = Task("later", WorkTaskStatus.Paused, DateTimeOffset.Parse("2026-08-14T14:00:00Z"));
|
||||
|
||||
var upcoming = BoardModel.SelectUpcomingTasks([parent, subtask, later], category: null, hasSubtasks: false);
|
||||
|
||||
Assert.Equal(["subtask", "top level", "later"], upcoming.Select(task => task.Title));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectUpcomingTasks_limits_results_to_eight_earliest_deadlines()
|
||||
{
|
||||
var start = DateTimeOffset.Parse("2026-08-14T09:00:00Z");
|
||||
var tasks = Enumerable.Range(0, 9)
|
||||
.Select(index => Task($"task {index}", WorkTaskStatus.Pending, start.AddHours(index)))
|
||||
.ToList();
|
||||
|
||||
var upcoming = BoardModel.SelectUpcomingTasks(tasks, category: null, hasSubtasks: false);
|
||||
|
||||
Assert.Equal(8, upcoming.Count);
|
||||
Assert.DoesNotContain(upcoming, task => task.Title == "task 8");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectUpcomingTasks_honors_active_category_and_has_subtasks_filters()
|
||||
{
|
||||
var dueAt = DateTimeOffset.Parse("2026-08-14T09:00:00Z");
|
||||
var developmentParent = Task("development parent", WorkTaskStatus.Pending, dueAt, category: "Development");
|
||||
developmentParent.SubTasks.Add(Task("development child", WorkTaskStatus.Pending, dueAt.AddHours(1), parentTaskId: 1, category: "Development"));
|
||||
var developmentLeaf = Task("development leaf", WorkTaskStatus.Pending, dueAt.AddHours(2), category: "Development");
|
||||
var researchParent = Task("research parent", WorkTaskStatus.Pending, dueAt.AddHours(-1), category: "Research");
|
||||
researchParent.SubTasks.Add(Task("research child", WorkTaskStatus.Pending, dueAt, parentTaskId: 2, category: "Research"));
|
||||
|
||||
var upcoming = BoardModel.SelectUpcomingTasks(
|
||||
[developmentParent, developmentParent.SubTasks[0], developmentLeaf, researchParent, researchParent.SubTasks[0]],
|
||||
category: "development",
|
||||
hasSubtasks: true);
|
||||
|
||||
var task = Assert.Single(upcoming);
|
||||
Assert.Equal("development parent", task.Title);
|
||||
}
|
||||
|
||||
private static WorkTask Task(string title, WorkTaskStatus status, DateTimeOffset? dueAt = null, int? parentTaskId = null, string? category = null) =>
|
||||
new()
|
||||
{
|
||||
Title = title,
|
||||
Status = status,
|
||||
DueAt = dueAt,
|
||||
ParentTaskId = parentTaskId,
|
||||
Category = category,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user