741 lines
31 KiB
C#
741 lines
31 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Data.Repositories;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Data.Tests;
|
|
|
|
public sealed class RepositoryTests
|
|
{
|
|
private static LiteDbContext NewInMemoryContext() => new(new MemoryStream());
|
|
|
|
// ── StudentRepository ─────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void StudentRepository_GetByGroup_FindetNurZugeordneteSchueler()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new StudentRepository(db);
|
|
var groupId = Guid.NewGuid();
|
|
var inGroup = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
|
var notInGroup = new Student { FirstName = "Ben", LastName = "Muster" };
|
|
repo.Save(inGroup);
|
|
repo.Save(notInGroup);
|
|
db.Memberships.Insert(new GroupMembership { StudentId = inGroup.Id, GroupId = groupId });
|
|
|
|
var result = repo.GetByGroup(groupId);
|
|
|
|
Assert.Single(result);
|
|
Assert.Equal(inGroup.Id, result[0].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void StudentRepository_GetAll_OhneInactiveFiltertDeaktivierteSchuelerAus()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new StudentRepository(db);
|
|
repo.Save(new Student { FirstName = "Anna", LastName = "Aktiv", IsActive = true });
|
|
repo.Save(new Student { FirstName = "Ben", LastName = "Inaktiv", IsActive = false });
|
|
|
|
Assert.Single(repo.GetAll(includeInactive: false));
|
|
Assert.Equal(2, repo.GetAll(includeInactive: true).Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void StudentRepository_Delete_LehntVerknuepfteDatenAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new StudentRepository(db);
|
|
var student = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
|
repo.Save(student);
|
|
db.Memberships.Insert(new GroupMembership { StudentId = student.Id, GroupId = Guid.NewGuid() });
|
|
db.Grades.Insert(new Grade { StudentId = student.Id, GroupId = Guid.NewGuid(), Value = "2" });
|
|
|
|
var references = repo.GetReferenceSummary(student.Id);
|
|
|
|
Assert.Equal(1, references.Memberships);
|
|
Assert.Equal(1, references.Grades);
|
|
Assert.Throws<InvalidOperationException>(() => repo.Delete(student.Id));
|
|
Assert.NotNull(repo.GetById(student.Id));
|
|
}
|
|
|
|
[Fact]
|
|
public void StudentRepository_Delete_EntferntUnverknuepftenSchueler()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new StudentRepository(db);
|
|
var student = new Student { FirstName = "Anna", LastName = "Beispiel" };
|
|
repo.Save(student);
|
|
|
|
repo.Delete(student.Id);
|
|
|
|
Assert.Null(repo.GetById(student.Id));
|
|
}
|
|
|
|
// ── GroupRepository ───────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void GroupRepository_Save_LehntUnbekanntesFachAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new GroupRepository(db);
|
|
var group = new LearningGroup { Name = "Mathe G", SchoolYear = "2025/26", SubjectId = Guid.NewGuid() };
|
|
|
|
Assert.Throws<InvalidOperationException>(() => repo.Save(group));
|
|
}
|
|
|
|
[Fact]
|
|
public void GroupRepository_Save_AkzeptiertVorhandenesFach()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var subjectRepo = new SubjectRepository(db);
|
|
var groupRepo = new GroupRepository(db);
|
|
var subject = new Subject { Name = "Mathematik" };
|
|
subjectRepo.Save(subject);
|
|
|
|
groupRepo.Save(new LearningGroup { Name = "Mathe G", SchoolYear = "2025/26", SubjectId = subject.Id });
|
|
|
|
Assert.NotNull(groupRepo.GetAll(includeInactive: true).FirstOrDefault(g => g.Name == "Mathe G"));
|
|
}
|
|
|
|
[Fact]
|
|
public void ArchivierteGruppe_BlockiertZentraleSchreibvorgaenge()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var groupRepo = new GroupRepository(db);
|
|
var group = new LearningGroup { Name = "8a", SchoolYear = "2025/26", IsActive = true };
|
|
groupRepo.Save(group);
|
|
group.IsActive = false;
|
|
groupRepo.Save(group);
|
|
|
|
var membership = new GroupMembership { GroupId = group.Id, StudentId = Guid.NewGuid() };
|
|
var exam = new Exam { GroupId = group.Id, Title = "Test" };
|
|
|
|
Assert.Throws<InvalidOperationException>(() => new GroupMembershipRepository(db).Save(membership));
|
|
Assert.Throws<InvalidOperationException>(() => new ExamRepository(db).Save(exam));
|
|
Assert.Throws<InvalidOperationException>(() => new GradeRepository(db).Save(
|
|
new Grade { GroupId = group.Id, StudentId = Guid.NewGuid(), Value = "2" }));
|
|
Assert.Throws<InvalidOperationException>(() => new UnitRepository(db).Save(
|
|
new Unit { GroupId = group.Id, Title = "Einheit" }));
|
|
Assert.Throws<InvalidOperationException>(() => new TimetableSlotRepository(db).Save(
|
|
new TimetableSlot { GroupId = group.Id, Weekday = DayOfWeek.Monday, PeriodNumber = 1 }));
|
|
}
|
|
|
|
[Fact]
|
|
public void ArchivierteGruppe_MussVorKorrekturSeparatReaktiviertWerden()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new GroupRepository(db);
|
|
var group = new LearningGroup { Name = "8a", SchoolYear = "2025/26", IsActive = true };
|
|
repo.Save(group);
|
|
group.IsActive = false;
|
|
repo.Save(group);
|
|
|
|
var archived = repo.GetById(group.Id)!;
|
|
archived.Name = "Geändert";
|
|
Assert.Throws<InvalidOperationException>(() => repo.Save(archived));
|
|
archived.IsActive = true;
|
|
Assert.Throws<InvalidOperationException>(() => repo.Save(archived));
|
|
|
|
archived.Name = "8a";
|
|
repo.Save(archived);
|
|
archived.Name = "8b";
|
|
repo.Save(archived);
|
|
|
|
Assert.Equal("8b", repo.GetById(group.Id)!.Name);
|
|
}
|
|
|
|
[Fact]
|
|
public void GroupRepository_Delete_LoeschtAlleAbhaengigenDatensaetzeKaskadierend()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var groupRepo = new GroupRepository(db);
|
|
var groupId = Guid.NewGuid();
|
|
groupRepo.Save(new LearningGroup { Id = groupId, Name = "Mathe G", SchoolYear = "2025/26" });
|
|
|
|
var studentId = Guid.NewGuid();
|
|
var membershipId = Guid.NewGuid();
|
|
db.Memberships.Insert(new GroupMembership { Id = membershipId, StudentId = studentId, GroupId = groupId });
|
|
|
|
var examId = Guid.NewGuid();
|
|
var examResultId = Guid.NewGuid();
|
|
db.Exams.Insert(new Exam { Id = examId, GroupId = groupId });
|
|
db.ExamResults.Insert(new ExamResult { Id = examResultId, ExamId = examId, StudentId = studentId });
|
|
|
|
var gradeId = Guid.NewGuid();
|
|
db.Grades.Insert(new Grade { Id = gradeId, GroupId = groupId, StudentId = studentId });
|
|
|
|
var unitId = Guid.NewGuid();
|
|
var lessonInUnitId = Guid.NewGuid();
|
|
db.Units.Insert(new Unit { Id = unitId, GroupId = groupId });
|
|
db.Lessons.Insert(new Lesson { Id = lessonInUnitId, UnitId = unitId, GroupId = groupId });
|
|
|
|
var looseLessonId = Guid.NewGuid();
|
|
db.Lessons.Insert(new Lesson { Id = looseLessonId, UnitId = Guid.NewGuid(), GroupId = groupId });
|
|
|
|
var sessionId = Guid.NewGuid();
|
|
var entryId = Guid.NewGuid();
|
|
db.ParticipationSessions.Insert(new ParticipationSession { Id = sessionId, GroupId = groupId });
|
|
db.ParticipationEntries.Insert(new ParticipationEntry { Id = entryId, SessionId = sessionId, StudentId = studentId });
|
|
|
|
var aspectId = Guid.NewGuid();
|
|
db.ParticipationAspects.Insert(new ParticipationAspect { Id = aspectId, GroupId = groupId, Key = "quality" });
|
|
|
|
var reportGradeId = Guid.NewGuid();
|
|
db.ReportGrades.Insert(new ReportGrade { Id = reportGradeId, GroupId = groupId, StudentId = studentId });
|
|
|
|
var gradingSchemeId = Guid.NewGuid();
|
|
db.GradingSchemes.Insert(new GradingScheme { Id = gradingSchemeId, GroupId = groupId });
|
|
|
|
var sectionId = Guid.NewGuid();
|
|
db.ParticipationSections.Insert(new ParticipationSection { Id = sectionId, GroupId = groupId });
|
|
|
|
var documentationId = Guid.NewGuid();
|
|
db.Documentation.Insert(new Documentation { Id = documentationId, GroupId = groupId, StudentId = studentId });
|
|
|
|
var taskId = Guid.NewGuid();
|
|
db.Tasks.Insert(new WorkTask { Id = taskId, GroupId = groupId });
|
|
|
|
var timeEntryId = Guid.NewGuid();
|
|
db.TimeEntries.Insert(new TimeEntry { Id = timeEntryId, GroupId = groupId, TaskId = taskId });
|
|
|
|
groupRepo.Delete(groupId);
|
|
|
|
Assert.Null(db.Groups.FindById(groupId));
|
|
Assert.Null(db.Memberships.FindById(membershipId));
|
|
Assert.Null(db.Exams.FindById(examId));
|
|
Assert.Null(db.ExamResults.FindById(examResultId));
|
|
Assert.Null(db.Grades.FindById(gradeId));
|
|
Assert.Null(db.Units.FindById(unitId));
|
|
Assert.Null(db.Lessons.FindById(lessonInUnitId));
|
|
Assert.Null(db.Lessons.FindById(looseLessonId));
|
|
Assert.Null(db.ParticipationSessions.FindById(sessionId));
|
|
Assert.Null(db.ParticipationEntries.FindById(entryId));
|
|
Assert.Null(db.ParticipationAspects.FindById(aspectId));
|
|
Assert.Null(db.ReportGrades.FindById(reportGradeId));
|
|
Assert.Null(db.GradingSchemes.FindById(gradingSchemeId));
|
|
Assert.Null(db.ParticipationSections.FindById(sectionId));
|
|
Assert.Null(db.Documentation.FindById(documentationId)?.GroupId);
|
|
Assert.Null(db.Tasks.FindById(taskId)?.GroupId);
|
|
Assert.Null(db.TimeEntries.FindById(timeEntryId)?.GroupId);
|
|
}
|
|
|
|
[Fact]
|
|
public void GroupRepository_Delete_LaesstDatenAndererGruppenUnberuehrt()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var groupRepo = new GroupRepository(db);
|
|
var deletedGroupId = Guid.NewGuid();
|
|
var otherGroupId = Guid.NewGuid();
|
|
groupRepo.Save(new LearningGroup { Id = deletedGroupId, Name = "Löschen", SchoolYear = "2025/26" });
|
|
groupRepo.Save(new LearningGroup { Id = otherGroupId, Name = "Bleibt", SchoolYear = "2025/26" });
|
|
|
|
var otherExamId = Guid.NewGuid();
|
|
db.Exams.Insert(new Exam { Id = otherExamId, GroupId = otherGroupId });
|
|
|
|
groupRepo.Delete(deletedGroupId);
|
|
|
|
Assert.Null(db.Groups.FindById(deletedGroupId));
|
|
Assert.NotNull(db.Groups.FindById(otherGroupId));
|
|
Assert.NotNull(db.Exams.FindById(otherExamId));
|
|
}
|
|
|
|
// ── GroupMembershipRepository ────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void GroupMembershipRepository_Save_LehntZweiteZuordnungFuerGleichesPaarAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new GroupMembershipRepository(db);
|
|
var studentId = Guid.NewGuid();
|
|
var groupId = Guid.NewGuid();
|
|
repo.Save(new GroupMembership { StudentId = studentId, GroupId = groupId });
|
|
|
|
var duplicate = new GroupMembership { StudentId = studentId, GroupId = groupId };
|
|
Assert.Throws<InvalidOperationException>(() => repo.Save(duplicate));
|
|
}
|
|
|
|
[Fact]
|
|
public void GroupMembershipRepository_Save_ErlaubtAktualisierenDerselbenZuordnung()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new GroupMembershipRepository(db);
|
|
var membership = new GroupMembership { StudentId = Guid.NewGuid(), GroupId = Guid.NewGuid(), Period = MembershipPeriod.FullYear };
|
|
repo.Save(membership);
|
|
|
|
membership.Period = MembershipPeriod.H1Only;
|
|
repo.Save(membership); // gleiche Id -> darf keine Ausnahme werfen
|
|
|
|
var reloaded = repo.GetByStudentAndGroup(membership.StudentId, membership.GroupId);
|
|
Assert.Equal(MembershipPeriod.H1Only, reloaded?.Period);
|
|
}
|
|
|
|
// ── ExamRepository ────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void ExamRepository_Delete_LoeschtZugehoerigeErgebnisseMit()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ExamRepository(db);
|
|
var exam = new Exam { GroupId = Guid.NewGuid() };
|
|
repo.Save(exam);
|
|
var resultId = Guid.NewGuid();
|
|
db.ExamResults.Insert(new ExamResult { Id = resultId, ExamId = exam.Id, StudentId = Guid.NewGuid() });
|
|
|
|
repo.Delete(exam.Id);
|
|
|
|
Assert.Null(repo.GetById(exam.Id));
|
|
Assert.Null(db.ExamResults.FindById(resultId));
|
|
}
|
|
|
|
[Fact]
|
|
public void ExamRepository_GetByGroup_SortiertAbsteigendNachDatum()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ExamRepository(db);
|
|
var groupId = Guid.NewGuid();
|
|
repo.Save(new Exam { GroupId = groupId, Title = "Früh", Date = new DateOnly(2025, 9, 1) });
|
|
repo.Save(new Exam { GroupId = groupId, Title = "Spät", Date = new DateOnly(2025, 11, 1) });
|
|
|
|
var result = repo.GetByGroup(groupId);
|
|
|
|
Assert.Equal("Spät", result[0].Title);
|
|
Assert.Equal("Früh", result[1].Title);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExamRepository_GetAll_UeberAlleGruppenHinwegSortiertAufsteigendNachDatum()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ExamRepository(db);
|
|
repo.Save(new Exam { GroupId = Guid.NewGuid(), Title = "Spät", Date = new DateOnly(2025, 11, 1) });
|
|
repo.Save(new Exam { GroupId = Guid.NewGuid(), Title = "Früh", Date = new DateOnly(2025, 9, 1) });
|
|
|
|
var result = repo.GetAll();
|
|
|
|
Assert.Equal("Früh", result[0].Title);
|
|
Assert.Equal("Spät", result[1].Title);
|
|
}
|
|
|
|
// ── SubjectRepository ─────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void SubjectRepository_Save_TrimmtNamenUndKuerzel()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SubjectRepository(db);
|
|
var subject = new Subject { Name = " Chemie ", ShortName = " Ch " };
|
|
|
|
repo.Save(subject);
|
|
|
|
var reloaded = repo.GetById(subject.Id);
|
|
Assert.Equal("Chemie", reloaded?.Name);
|
|
Assert.Equal("Ch", reloaded?.ShortName);
|
|
}
|
|
|
|
[Fact]
|
|
public void SubjectRepository_Save_LehntLeerenNamenAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SubjectRepository(db);
|
|
|
|
Assert.Throws<ArgumentException>(() => repo.Save(new Subject { Name = " " }));
|
|
}
|
|
|
|
[Fact]
|
|
public void SubjectRepository_Save_LehntDuplikatUnabhaengigVonGrossKleinschreibungAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SubjectRepository(db);
|
|
repo.Save(new Subject { Name = "Chemie" });
|
|
|
|
Assert.Throws<InvalidOperationException>(() => repo.Save(new Subject { Name = "chemie" }));
|
|
}
|
|
|
|
[Fact]
|
|
public void SubjectRepository_Delete_WirdBlockiertWennGruppeDasFachVerwendet()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var subjectRepo = new SubjectRepository(db);
|
|
var subject = new Subject { Name = "Chemie" };
|
|
subjectRepo.Save(subject);
|
|
db.Groups.Insert(new LearningGroup { Name = "Chemie G", SchoolYear = "2025/26", SubjectId = subject.Id });
|
|
|
|
Assert.Throws<InvalidOperationException>(() => subjectRepo.Delete(subject.Id));
|
|
}
|
|
|
|
[Fact]
|
|
public void SubjectRepository_Delete_FunktioniertWennUnbenutzt()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SubjectRepository(db);
|
|
var subject = new Subject { Name = "Chemie" };
|
|
repo.Save(subject);
|
|
|
|
repo.Delete(subject.Id);
|
|
|
|
Assert.Null(repo.GetById(subject.Id));
|
|
}
|
|
|
|
// ── GradingSchemeRepository ───────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void GradingSchemeRepository_UnterscheidetGruppenspezifischesSchemaVonVoreinstellung()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new GradingSchemeRepository(db);
|
|
var groupId = Guid.NewGuid();
|
|
repo.Save(new GradingScheme { GroupId = groupId, ExamsPercent = 60, ParticipationPercent = 30, OtherPercent = 10 });
|
|
repo.Save(new GradingScheme { GroupType = GroupType.Class, ExamsPercent = 50, ParticipationPercent = 40, OtherPercent = 10 });
|
|
|
|
var forGroup = repo.GetByGroup(groupId);
|
|
var defaultForClass = repo.GetDefaultForType(GroupType.Class);
|
|
var defaultForCourse = repo.GetDefaultForType(GroupType.Course);
|
|
|
|
Assert.Equal(60, forGroup?.ExamsPercent);
|
|
Assert.Equal(50, defaultForClass?.ExamsPercent);
|
|
Assert.Null(defaultForCourse);
|
|
}
|
|
|
|
// ── ReportGradeRepository ─────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void ReportGradeRepository_GetByStudentGroupPeriod_UnterscheidetZeitraeume()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ReportGradeRepository(db);
|
|
var studentId = Guid.NewGuid();
|
|
var groupId = Guid.NewGuid();
|
|
repo.Save(new ReportGrade { StudentId = studentId, GroupId = groupId, Period = "1. Halbjahr", CalculatedValue = "2" });
|
|
repo.Save(new ReportGrade { StudentId = studentId, GroupId = groupId, Period = "2. Halbjahr", CalculatedValue = "3" });
|
|
|
|
var h1 = repo.GetByStudentGroupPeriod(studentId, groupId, "1. Halbjahr");
|
|
var h2 = repo.GetByStudentGroupPeriod(studentId, groupId, "2. Halbjahr");
|
|
var unbekannt = repo.GetByStudentGroupPeriod(studentId, groupId, "Gesamtes Schuljahr");
|
|
|
|
Assert.Equal("2", h1?.CalculatedValue);
|
|
Assert.Equal("3", h2?.CalculatedValue);
|
|
Assert.Null(unbekannt);
|
|
}
|
|
|
|
// ── ParticipationSessionRepository ───────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void ParticipationSessionRepository_Delete_LoeschtZugehoerigeEintraegeMit()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ParticipationSessionRepository(db);
|
|
var session = new ParticipationSession { GroupId = Guid.NewGuid() };
|
|
repo.Save(session);
|
|
var entryId = Guid.NewGuid();
|
|
db.ParticipationEntries.Insert(new ParticipationEntry { Id = entryId, SessionId = session.Id, StudentId = Guid.NewGuid() });
|
|
|
|
repo.Delete(session.Id);
|
|
|
|
Assert.Null(repo.GetById(session.Id));
|
|
Assert.Null(db.ParticipationEntries.FindById(entryId));
|
|
}
|
|
|
|
[Fact]
|
|
public void ParticipationEntry_EindeutigerIndex_LehntZweitenEintragFuerGleicheSitzungUndSchuelerAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ParticipationRepository(db);
|
|
var sessionId = Guid.NewGuid();
|
|
var studentId = Guid.NewGuid();
|
|
repo.Save(new ParticipationEntry { SessionId = sessionId, StudentId = studentId });
|
|
|
|
Assert.Throws<LiteDB.LiteException>(() =>
|
|
db.ParticipationEntries.Insert(new ParticipationEntry { SessionId = sessionId, StudentId = studentId }));
|
|
}
|
|
|
|
// ── DocumentationRepository ───────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void DocumentationRepository_Delete_MarkiertNurAlsGeloescht()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new DocumentationRepository(db);
|
|
var doc = new Documentation { StudentId = Guid.NewGuid(), Title = "Gespräch" };
|
|
repo.Save(doc);
|
|
|
|
repo.Delete(doc.Id);
|
|
|
|
Assert.Empty(repo.GetByStudent(doc.StudentId));
|
|
var raw = db.Documentation.FindById(doc.Id);
|
|
Assert.NotNull(raw);
|
|
Assert.True(raw.IsDeleted);
|
|
Assert.NotNull(raw.DeletedAt);
|
|
}
|
|
|
|
[Fact]
|
|
public void DocumentationRepository_HardDelete_EntferntDenEintragEndgueltig()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new DocumentationRepository(db);
|
|
var doc = new Documentation { StudentId = Guid.NewGuid(), Title = "Vorkommnis" };
|
|
repo.Save(doc);
|
|
|
|
repo.HardDelete(doc.Id);
|
|
|
|
Assert.Null(db.Documentation.FindById(doc.Id));
|
|
}
|
|
|
|
[Fact]
|
|
public void DocumentationRepository_GetAll_FiltertGeloeschteEintraegeUndUmfasstAlleSchueler()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new DocumentationRepository(db);
|
|
var visible = new Documentation { StudentId = Guid.NewGuid(), Title = "Sichtbar" };
|
|
var deleted = new Documentation { StudentId = Guid.NewGuid(), Title = "Gelöscht" };
|
|
repo.Save(visible);
|
|
repo.Save(deleted);
|
|
repo.Delete(deleted.Id);
|
|
|
|
var all = repo.GetAll();
|
|
|
|
Assert.Single(all);
|
|
Assert.Equal(visible.Id, all[0].Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void DocumentationRepository_HardDelete_EntferntAuchDieAnhaenge()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new DocumentationRepository(db);
|
|
var storage = new LiteAttachmentStorage(db);
|
|
string attachmentId;
|
|
using (var ms = new MemoryStream([1, 2, 3]))
|
|
attachmentId = storage.Upload("brief.pdf", ms);
|
|
|
|
var doc = new Documentation { StudentId = Guid.NewGuid(), Title = "Elternbrief" };
|
|
doc.Attachments.Add(new DocumentAttachment { StorageId = attachmentId, FileName = "brief.pdf", SizeBytes = 3 });
|
|
repo.Save(doc);
|
|
|
|
repo.HardDelete(doc.Id);
|
|
|
|
Assert.Null(db.Documentation.FindById(doc.Id));
|
|
Assert.Null(storage.OpenRead(attachmentId));
|
|
}
|
|
|
|
// ── LessonRepository ──────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void LessonRepository_GetByUnit_SortiertNachDatumDannStundennummer()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new LessonRepository(db);
|
|
var unitId = Guid.NewGuid();
|
|
var groupId = Guid.NewGuid();
|
|
|
|
// Doppelstunde am selben Tag: Stunde 2 vor Stunde 1 eingefügt, muss trotzdem
|
|
// nach LessonNumber sortiert erscheinen.
|
|
repo.Save(new Lesson { UnitId = unitId, GroupId = groupId, Date = new DateOnly(2025, 9, 8), LessonNumber = 2 });
|
|
repo.Save(new Lesson { UnitId = unitId, GroupId = groupId, Date = new DateOnly(2025, 9, 8), LessonNumber = 1 });
|
|
repo.Save(new Lesson { UnitId = unitId, GroupId = groupId, Date = new DateOnly(2025, 9, 1), LessonNumber = 1 });
|
|
|
|
var result = repo.GetByUnit(unitId);
|
|
|
|
Assert.Equal(new DateOnly(2025, 9, 1), result[0].Date);
|
|
Assert.Equal(new DateOnly(2025, 9, 8), result[1].Date);
|
|
Assert.Equal(1, result[1].LessonNumber);
|
|
Assert.Equal(new DateOnly(2025, 9, 8), result[2].Date);
|
|
Assert.Equal(2, result[2].LessonNumber);
|
|
}
|
|
|
|
// ── ShorthandCodeRepository ───────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void ShorthandCodeRepository_Save_LehntDuplikatCodeAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ShorthandCodeRepository(db);
|
|
repo.Save(new ShorthandCode { Code = "Tb", Label = "Tafelbild" });
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
repo.Save(new ShorthandCode { Code = "tb", Label = "Anderes Tafelbild" }));
|
|
}
|
|
|
|
[Fact]
|
|
public void ShorthandCodeRepository_GetAll_SortiertNachCode()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ShorthandCodeRepository(db);
|
|
repo.Save(new ShorthandCode { Code = "SH", Label = "Schülerheft" });
|
|
repo.Save(new ShorthandCode { Code = "AB", Label = "Arbeitsblatt" });
|
|
|
|
var result = repo.GetAll();
|
|
|
|
Assert.Equal(["AB", "SH"], result.Select(c => c.Code));
|
|
}
|
|
|
|
[Fact]
|
|
public void ShorthandCodeRepository_Delete_EntferntEintrag()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new ShorthandCodeRepository(db);
|
|
repo.Save(new ShorthandCode { Code = "Tb", Label = "Tafelbild" });
|
|
var id = repo.GetAll().Single().Id;
|
|
|
|
repo.Delete(id);
|
|
|
|
Assert.Empty(repo.GetAll());
|
|
}
|
|
|
|
// ── AlternativeLessonPathRepository ───────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void AlternativeLessonPathRepository_Save_LehntDuplikatNamenAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new AlternativeLessonPathRepository(db);
|
|
repo.Save(new AlternativeLessonPath { Name = "Kurzversion" });
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
repo.Save(new AlternativeLessonPath { Name = "kurzversion" }));
|
|
}
|
|
|
|
[Fact]
|
|
public void AlternativeLessonPathRepository_GetById_FindetGespeichertenEintragMitBeschreibung()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new AlternativeLessonPathRepository(db);
|
|
var entry = new AlternativeLessonPath { Name = "Kurzversion", Description = "Bei Zeitmangel." };
|
|
repo.Save(entry);
|
|
|
|
var found = repo.GetById(entry.Id);
|
|
|
|
Assert.NotNull(found);
|
|
Assert.Equal("Kurzversion", found!.Name);
|
|
Assert.Equal("Bei Zeitmangel.", found.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void AlternativeLessonPathRepository_Delete_EntferntEintrag()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new AlternativeLessonPathRepository(db);
|
|
repo.Save(new AlternativeLessonPath { Name = "Kurzversion" });
|
|
var id = repo.GetAll().Single().Id;
|
|
|
|
repo.Delete(id);
|
|
|
|
Assert.Empty(repo.GetAll());
|
|
}
|
|
|
|
// ── TimetableSlotRepository ───────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void TimetableSlotRepository_GetByGroup_FindetNurSlotsDerGruppe()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new TimetableSlotRepository(db);
|
|
var groupA = Guid.NewGuid();
|
|
var groupB = Guid.NewGuid();
|
|
repo.Save(new TimetableSlot { GroupId = groupA, Weekday = DayOfWeek.Monday, PeriodNumber = 1 });
|
|
repo.Save(new TimetableSlot { GroupId = groupB, Weekday = DayOfWeek.Monday, PeriodNumber = 2 });
|
|
|
|
var result = repo.GetByGroup(groupA);
|
|
|
|
Assert.Single(result);
|
|
Assert.Equal(groupA, result[0].GroupId);
|
|
}
|
|
|
|
[Fact]
|
|
public void TimetableSlotRepository_Save_LehntDoppelbelegungDerselbenStundeAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new TimetableSlotRepository(db);
|
|
repo.Save(new TimetableSlot { GroupId = Guid.NewGuid(), Weekday = DayOfWeek.Tuesday, PeriodNumber = 3 });
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
repo.Save(new TimetableSlot { GroupId = Guid.NewGuid(), Weekday = DayOfWeek.Tuesday, PeriodNumber = 3 }));
|
|
}
|
|
|
|
[Fact]
|
|
public void TimetableSlotRepository_Save_AktualisierenDesselbenSlotsIstErlaubt()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new TimetableSlotRepository(db);
|
|
var slot = new TimetableSlot { GroupId = Guid.NewGuid(), Weekday = DayOfWeek.Tuesday, PeriodNumber = 3 };
|
|
repo.Save(slot);
|
|
|
|
slot.Room = "R204";
|
|
repo.Save(slot);
|
|
|
|
Assert.Equal("R204", repo.GetAll().Single().Room);
|
|
}
|
|
|
|
// ── SchoolHolidayRepository ───────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void SchoolHolidayRepository_GetAll_SortiertNachStartdatum()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SchoolHolidayRepository(db);
|
|
repo.Save(new SchoolHoliday { Name = "Sommerferien", StartDate = new DateOnly(2026, 7, 1), EndDate = new DateOnly(2026, 8, 10) });
|
|
repo.Save(new SchoolHoliday { Name = "Osterferien", StartDate = new DateOnly(2026, 3, 30), EndDate = new DateOnly(2026, 4, 10) });
|
|
|
|
var result = repo.GetAll();
|
|
|
|
Assert.Equal("Osterferien", result[0].Name);
|
|
Assert.Equal("Sommerferien", result[1].Name);
|
|
}
|
|
|
|
// ── SupervisionDutyRepository ─────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void SupervisionDutyRepository_Save_LehntDoppelbelegungDerselbenPauseAb()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SupervisionDutyRepository(db);
|
|
repo.Save(new SupervisionDuty { Weekday = DayOfWeek.Monday, AfterPeriod = 2, Location = "Pausenhof" });
|
|
|
|
Assert.Throws<InvalidOperationException>(() =>
|
|
repo.Save(new SupervisionDuty { Weekday = DayOfWeek.Monday, AfterPeriod = 2, Location = "Bibliothek" }));
|
|
}
|
|
|
|
[Fact]
|
|
public void SupervisionDutyRepository_Save_AktualisierenDerselbenAufsichtIstErlaubt()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SupervisionDutyRepository(db);
|
|
var duty = new SupervisionDuty { Weekday = DayOfWeek.Monday, AfterPeriod = 2, Location = "Pausenhof" };
|
|
repo.Save(duty);
|
|
|
|
duty.Location = "Bibliothek";
|
|
repo.Save(duty);
|
|
|
|
Assert.Equal("Bibliothek", repo.GetAll().Single().Location);
|
|
}
|
|
|
|
[Fact]
|
|
public void SupervisionDutyRepository_GetAll_SortiertNachWochentagUndPause()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SupervisionDutyRepository(db);
|
|
repo.Save(new SupervisionDuty { Weekday = DayOfWeek.Tuesday, AfterPeriod = 1, Location = "A" });
|
|
repo.Save(new SupervisionDuty { Weekday = DayOfWeek.Monday, AfterPeriod = 4, Location = "B" });
|
|
repo.Save(new SupervisionDuty { Weekday = DayOfWeek.Monday, AfterPeriod = 2, Location = "C" });
|
|
|
|
var result = repo.GetAll();
|
|
|
|
Assert.Equal(["C", "B", "A"], result.Select(d => d.Location));
|
|
}
|
|
|
|
// ── SubstitutionEntryRepository ───────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void SubstitutionEntryRepository_GetByDate_FindetNurEintraegeDesTages()
|
|
{
|
|
using var db = NewInMemoryContext();
|
|
var repo = new SubstitutionEntryRepository(db);
|
|
repo.Save(new SubstitutionEntry { Date = new DateOnly(2026, 3, 12), Kind = SubstitutionKind.Lesson, PeriodNumber = 3, Description = "Vertretung 8a" });
|
|
repo.Save(new SubstitutionEntry { Date = new DateOnly(2026, 3, 13), Kind = SubstitutionKind.Supervision, AfterPeriod = 2, Description = "Vertretung Hr. Müller" });
|
|
|
|
var result = repo.GetByDate(new DateOnly(2026, 3, 12));
|
|
|
|
Assert.Single(result);
|
|
Assert.Equal("Vertretung 8a", result[0].Description);
|
|
}
|
|
}
|