Kompetenzen fast fertig

This commit is contained in:
2026-08-16 02:32:12 +02:00
parent 7c7fe6dfcb
commit 4437f951d9
22 changed files with 979 additions and 29 deletions
@@ -0,0 +1,68 @@
using LehrerApp.Core.Models;
using LehrerApp.Core.Services;
using LehrerApp.Desktop.ViewModels.Groups;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class CompetencyOverviewViewModelTests
{
[Fact]
public void Initialize_ZeigtAbdeckungGruppenmittelUndVorausgewaehltesSchuelerprofil()
{
var subjectId = Guid.NewGuid();
var group = new LearningGroup { SubjectId = subjectId, GradeLevel = 8 };
var student = new Student { FirstName = "Ada", LastName = "Lovelace" };
var units = new FakeUnits();
units.Add(new Unit
{
GroupId = group.Id, Status = UnitStatus.Completed, Competencies = ["K1"],
});
var exam = new Exam
{
GroupId = group.Id,
Status = ExamStatus.Graded,
Tasks = [new ExamTask { MaxPoints = 10, CompetencyCodes = ["K1"] }],
};
var results = new FakeResults();
results.Add(new ExamResult { ExamId = exam.Id, StudentId = student.Id, Points = [5] });
var catalog = new FakeCompetencyDomains();
catalog.Add(new CompetencyDomain
{
SubjectId = subjectId,
GradeLevel = 8,
Name = "Bereich",
Items = [new CompetencyItem { Code = "K1", Description = "Kompetenz" }],
});
var vm = new CompetencyOverviewTabViewModel(units, new FakeExams([exam]), results,
catalog, new FakeStudents([student]), new CompetencyAnalysisService());
vm.Initialize(group);
var row = Assert.Single(vm.Rows);
Assert.Equal("1× behandelt", row.InstructionCoverage);
Assert.Equal("1× geprüft", row.ExamCoverage);
Assert.Contains("50 %", row.GroupResult);
Assert.Contains("50 %", row.StudentResult);
Assert.Equal("Wiederholungsbedarf", row.Recommendation);
Assert.Equal(student.Id, vm.SelectedStudent?.Id);
}
[Fact]
public void ReviewThreshold_Aendern_AktualisiertHinweis()
{
var item = new CompetencyAnalysisItem
{
DomainName = "Bereich",
DomainCode = "B",
Code = "K1",
Description = "Kompetenz",
GroupScore = new CompetencyScore(5, 10, 1, 1),
};
var row = new CompetencyOverviewRow(item, null, 60);
row.SetThreshold(40);
Assert.Equal("Stand solide", row.Recommendation);
}
}
+2 -1
View File
@@ -234,7 +234,8 @@ public class FakeCompetencyDomains : ICompetencyDomainRepository
private readonly List<CompetencyDomain> _all = [];
public void Add(CompetencyDomain d) => _all.Add(d);
public List<CompetencyDomain> GetBySubjectAndGrade(Guid subjectId, int gradeLevel) =>
_all.Where(d => d.SubjectId == subjectId && d.GradeLevel == gradeLevel).ToList();
_all.Where(d => d.SubjectId == subjectId && d.GradeLevel == gradeLevel)
.OrderBy(d => d.SortOrder).ToList();
public CompetencyDomain? GetById(Guid id) => _all.FirstOrDefault(d => d.Id == id);
public void Save(CompetencyDomain domain) { _all.RemoveAll(d => d.Id == domain.Id); _all.Add(domain); }
public void Delete(Guid id) => _all.RemoveAll(d => d.Id == id);
@@ -22,7 +22,9 @@ public sealed class GroupDetailViewModelTests
students, memberships, groups, new FakeCompetencyDomains()),
new GradeOverviewTabViewModel(grades, exams, new FakeResults(), students, memberships, new GradingService()),
new PlanningTabViewModel(new FakeUnits(), new FakeLessons(), groups, subjects,
new FakeCompetencyDomains(), TestSupport.BuildAiSettingsService()));
new FakeCompetencyDomains(), TestSupport.BuildAiSettingsService()),
new CompetencyOverviewTabViewModel(new FakeUnits(), exams, new FakeResults(),
new FakeCompetencyDomains(), students, new CompetencyAnalysisService()));
vm.LoadGroup(group.Id);
vm.SelectedExam = vm.Exams.First(e => e.Id == exam.Id);
@@ -9,7 +9,8 @@ namespace LehrerApp.Desktop.Tests;
public sealed class SettingsViewModelTests
{
private static SettingsViewModel BuildViewModel(FakeSchoolHolidays? holidays = null,
FakeSupervisionDuties? supervisionDuties = null)
FakeSupervisionDuties? supervisionDuties = null,
FakeSubjects? subjects = null, FakeCompetencyDomains? competencyDomains = null)
{
// Bewusst kein "using": SchoolCalendarSettingsService liest den Pfad erst bei SetState,
// das Verzeichnis muss über die Lebensdauer des ViewModels bestehen bleiben.
@@ -18,7 +19,7 @@ public sealed class SettingsViewModelTests
Directory.CreateDirectory(tempPath);
return new SettingsViewModel(
new FakeSubjects([]), new FakeCompetencyDomains(), new FakeGradingKeyTemplates(),
subjects ?? new FakeSubjects([]), competencyDomains ?? new FakeCompetencyDomains(), new FakeGradingKeyTemplates(),
new FakeSchemes(), new GradingService(), new BackupService(tempPath),
new DatabaseEncryptionService(), new AppLockService(tempPath),
new LiteDbContext(new MemoryStream()), new PrivacySettingsService(tempPath),
@@ -219,4 +220,82 @@ public sealed class SettingsViewModelTests
Assert.Empty(duties.GetAll());
Assert.Empty(vm.SupervisionDuties);
}
[Fact]
public void Kompetenzbereiche_Umsortieren_PersistiertSortOrder()
{
var subject = new Subject { Name = "Biologie", ShortName = "Bio" };
var repository = new FakeCompetencyDomains();
repository.Add(new CompetencyDomain
{
SubjectId = subject.Id, GradeLevel = 10, Name = "Erster Bereich", SortOrder = 0,
});
repository.Add(new CompetencyDomain
{
SubjectId = subject.Id, GradeLevel = 10, Name = "Zweiter Bereich", SortOrder = 1,
});
var vm = BuildViewModel(subjects: new FakeSubjects([subject]), competencyDomains: repository);
vm.CatalogSubject = vm.Subjects.Single();
vm.Domains[1].MoveUpCommand.Execute(null);
Assert.Equal(["Zweiter Bereich", "Erster Bereich"], vm.Domains.Select(x => x.Name));
var stored = repository.GetBySubjectAndGrade(subject.Id, 10);
Assert.Equal(["Zweiter Bereich", "Erster Bereich"], stored.Select(x => x.Name));
Assert.Equal([0, 1], stored.Select(x => x.SortOrder));
}
[Fact]
public void Kompetenzen_Umsortieren_PersistiertSortOrder()
{
var repository = new FakeCompetencyDomains();
var domain = new CompetencyDomain
{
Name = "Bereich",
Items =
[
new CompetencyItem { Code = "A", Description = "Erste", SortOrder = 0 },
new CompetencyItem { Code = "B", Description = "Zweite", SortOrder = 1 },
],
};
repository.Add(domain);
var vm = new DomainEditItem(domain, repository);
vm.Items[1].MoveUpCommand.Execute(null);
Assert.Equal(["B", "A"], vm.Items.Select(x => x.Code));
var stored = repository.GetById(domain.Id)!;
Assert.Equal(["B", "A"], stored.Items.Select(x => x.Code));
Assert.Equal([0, 1], stored.Items.Select(x => x.SortOrder));
}
[Fact]
public void KatalogKopieren_BereitetSichereVorschauFuerZielstufeVor()
{
var subject = new Subject { Name = "Biologie", ShortName = "Bio" };
var repository = new FakeCompetencyDomains();
repository.Add(new CompetencyDomain
{
SubjectId = subject.Id,
GradeLevel = 10,
Name = "Erkenntnisgewinnung",
Code = "EG",
Items = [new CompetencyItem { Code = "EG1", Description = "Modelle verwenden" }],
});
var vm = BuildViewModel(subjects: new FakeSubjects([subject]), competencyDomains: repository);
vm.CatalogSubject = vm.Subjects.Single();
var preview = vm.PrepareCatalogCopy(11);
Assert.NotNull(preview);
Assert.Equal(11, preview.GradeLevel);
Assert.Equal(1, preview.NewDomains);
Assert.Equal(1, preview.NewCompetencies);
vm.ApplyCatalogImport(preview, CompetencyCatalogImportMode.Merge, new HashSet<string>());
var copied = repository.GetBySubjectAndGrade(subject.Id, 11);
Assert.Single(copied);
Assert.NotEqual(repository.GetBySubjectAndGrade(subject.Id, 10)[0].Id, copied[0].Id);
Assert.Equal("EG1", copied[0].Items.Single().Code);
}
}