Arbeitszeit: Aufgabenverwaltung (Kapitel 6.1)
Navigationspunkt "Arbeitszeit" zeigt jetzt eine echte Aufgabenliste statt eines Placeholders: Filter nach Status/Kategorie/Gruppe (Standard blendet Erledigtes aus), Sortierung nach Fälligkeit, Anlegen/Bearbeiten-Dialog, Status per Klick durchschalten.
This commit is contained in:
@@ -270,6 +270,16 @@ public class FakeSubstitutionEntries : ISubstitutionEntryRepository
|
||||
public void Delete(Guid id) => _all.RemoveAll(e => e.Id == id);
|
||||
}
|
||||
|
||||
public class FakeWorkTasks : IWorkTaskRepository
|
||||
{
|
||||
private readonly List<WorkTask> _all = [];
|
||||
public void Add(WorkTask t) => _all.Add(t);
|
||||
public List<WorkTask> GetByStatus(WorkTaskStatus status) => _all.Where(t => t.Status == status).ToList();
|
||||
public List<WorkTask> GetAll() => _all.ToList();
|
||||
public void Save(WorkTask task) { _all.RemoveAll(t => t.Id == task.Id); _all.Add(task); }
|
||||
public void Delete(Guid id) => _all.RemoveAll(t => t.Id == id);
|
||||
}
|
||||
|
||||
public class FakeReportGrades : IReportGradeRepository
|
||||
{
|
||||
private readonly List<ReportGrade> _all = [];
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.ViewModels.Workload;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
public sealed class WorkTaskListViewModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void Load_BlendetErledigteAufgabenStandardmaessigAus()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "Offen", Status = WorkTaskStatus.Open });
|
||||
tasks.Add(new WorkTask { Title = "Erledigt", Status = WorkTaskStatus.Done });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]));
|
||||
|
||||
Assert.Single(vm.Tasks);
|
||||
Assert.Equal("Offen", vm.Tasks[0].Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StatusFilter_Alle_ZeigtAuchErledigteAufgaben()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "Erledigt", Status = WorkTaskStatus.Done });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]))
|
||||
{
|
||||
StatusFilter = WorkTaskListViewModel.AllFilter,
|
||||
};
|
||||
|
||||
Assert.Single(vm.Tasks);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CategoryFilter_FiltertNachKategorie()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "Korrektur", Category = TaskCategory.Correction });
|
||||
tasks.Add(new WorkTask { Title = "Vorbereitung", Category = TaskCategory.Preparation });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]))
|
||||
{
|
||||
CategoryFilter = TaskCategoryDisplay.Label(TaskCategory.Correction),
|
||||
};
|
||||
|
||||
Assert.Single(vm.Tasks);
|
||||
Assert.Equal("Korrektur", vm.Tasks[0].Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GroupFilter_OhneGruppe_ZeigtNurAufgabenOhneGroupId()
|
||||
{
|
||||
var group = new LearningGroup { Name = "8a" };
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "Mit Gruppe", GroupId = group.Id });
|
||||
tasks.Add(new WorkTask { Title = "Ohne Gruppe", GroupId = null });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([group]))
|
||||
{
|
||||
GroupFilter = WorkTaskListViewModel.NoGroupFilter,
|
||||
};
|
||||
|
||||
Assert.Single(vm.Tasks);
|
||||
Assert.Equal("Ohne Gruppe", vm.Tasks[0].Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CycleStatus_WechseltVonOffenNachInBearbeitung()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "T", Status = WorkTaskStatus.Open });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]))
|
||||
{
|
||||
StatusFilter = WorkTaskListViewModel.AllFilter,
|
||||
};
|
||||
|
||||
vm.CycleStatusCommand.Execute(vm.Tasks[0]);
|
||||
|
||||
Assert.Equal(WorkTaskStatus.InProgress, vm.Tasks[0].Model.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CycleStatus_VonErledigtSpringtZurueckZuOffen()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "T", Status = WorkTaskStatus.Done });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]))
|
||||
{
|
||||
StatusFilter = WorkTaskListViewModel.AllFilter,
|
||||
};
|
||||
|
||||
vm.CycleStatusCommand.Execute(vm.Tasks[0]);
|
||||
|
||||
Assert.Equal(WorkTaskStatus.Open, vm.Tasks[0].Model.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeleteTask_EntferntAufgabeAusDerListe()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "T" });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]));
|
||||
|
||||
vm.DeleteTaskCommand.Execute(vm.Tasks[0]);
|
||||
|
||||
Assert.Empty(vm.Tasks);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddTask_RuftOnEditTaskAufUndSpeichertErgebnis()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]));
|
||||
vm.OnEditTask = _ => Task.FromResult<WorkTask?>(new WorkTask { Title = "Neu" });
|
||||
|
||||
await vm.AddTaskCommand.ExecuteAsync(null);
|
||||
|
||||
Assert.Single(vm.Tasks);
|
||||
Assert.Equal("Neu", vm.Tasks[0].Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tasks_SindNachFaelligkeitSortiertUnbefristeteAmEnde()
|
||||
{
|
||||
var tasks = new FakeWorkTasks();
|
||||
tasks.Add(new WorkTask { Title = "Ohne Frist", DueDate = null });
|
||||
tasks.Add(new WorkTask { Title = "Spät fällig", DueDate = DateOnly.FromDateTime(DateTime.Today.AddDays(10)) });
|
||||
tasks.Add(new WorkTask { Title = "Bald fällig", DueDate = DateOnly.FromDateTime(DateTime.Today.AddDays(1)) });
|
||||
var vm = new WorkTaskListViewModel(tasks, new FakeGroups([]));
|
||||
|
||||
Assert.Equal(["Bald fällig", "Spät fällig", "Ohne Frist"], vm.Tasks.Select(t => t.Title));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AddEditWorkTaskDialogViewModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void Save_OhneTitel_SetztFehlerUndErzeugtKeinResult()
|
||||
{
|
||||
var vm = new AddEditWorkTaskDialogViewModel(null, []);
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Null(vm.Result);
|
||||
Assert.NotEmpty(vm.TitleError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_MitGueltigenDaten_ErzeugtWorkTask()
|
||||
{
|
||||
var group = new LearningGroup { Name = "8a" };
|
||||
var vm = new AddEditWorkTaskDialogViewModel(null, [group])
|
||||
{
|
||||
Title = "Klausur korrigieren",
|
||||
SelectedCategory = TaskCategoryDisplay.Label(TaskCategory.Correction),
|
||||
SelectedGroup = group,
|
||||
DueDateText = "24.12.2026",
|
||||
EstimatedMinutesText = "90",
|
||||
};
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.NotNull(vm.Result);
|
||||
Assert.Equal("Klausur korrigieren", vm.Result!.Title);
|
||||
Assert.Equal(TaskCategory.Correction, vm.Result.Category);
|
||||
Assert.Equal(group.Id, vm.Result.GroupId);
|
||||
Assert.Equal(new DateOnly(2026, 12, 24), vm.Result.DueDate);
|
||||
Assert.Equal(90, vm.Result.EstimatedMinutes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_MitUngueltigemDatum_SetztFehler()
|
||||
{
|
||||
var vm = new AddEditWorkTaskDialogViewModel(null, [])
|
||||
{
|
||||
Title = "T",
|
||||
DueDateText = "nicht-ein-datum",
|
||||
};
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Null(vm.Result);
|
||||
Assert.NotEmpty(vm.DueDateError);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Save_BestehendeAufgabe_BehaeltIdUndStatus()
|
||||
{
|
||||
var source = new WorkTask { Title = "Alt", Status = WorkTaskStatus.InProgress };
|
||||
var vm = new AddEditWorkTaskDialogViewModel(source, []) { Title = "Neu" };
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Equal(source.Id, vm.Result!.Id);
|
||||
Assert.Equal(WorkTaskStatus.InProgress, vm.Result.Status);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user