130 lines
7.1 KiB
C#
130 lines
7.1 KiB
C#
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Students;
|
|
using LehrerApp.Templating;
|
|
using Xunit;
|
|
|
|
namespace LehrerApp.Desktop.Tests;
|
|
|
|
public sealed class StudentReportTests
|
|
{
|
|
private readonly Student _student = new() { FirstName = "Erika", LastName = "Beispiel" };
|
|
private readonly LearningGroup _group = new() { Name = "9 Ch G", SchoolYear = "2026/27" };
|
|
private readonly DateOnly _date = new(2026, 10, 1);
|
|
private readonly FakeDocumentation _docs = new();
|
|
private readonly FakeEntries _entries = new();
|
|
private readonly FakeAspects _aspects = new();
|
|
private readonly List<ParticipationSession> _sessions = [];
|
|
|
|
private StudentReportService Service() => new(new FakeSessions(_sessions), _entries, _aspects,
|
|
new FakeExams([]), new FakeResults(), new FakeGrades(), new FakeMemberships([]),
|
|
new FakeCompetencyDomains(), _docs, new GradingService(), new CompetencyAnalysisService());
|
|
|
|
private Dictionary<string, PlaceholderValue> Build(StudentReportOptions? options = null) => Service().Build(
|
|
_student, _group, StudentReportTemplate.Create(), options ?? new(_date, _date.AddMonths(1), null, IncludeInterim: false));
|
|
|
|
[Fact]
|
|
public void Dokumentation_IstAufSchuelerGruppeZeitraumUndFreigabeBegrenzt()
|
|
{
|
|
Documentation Doc(string title) => new() { StudentId = _student.Id, GroupId = _group.Id, Date = _date, Title = title };
|
|
_docs.Add(Doc("sichtbar"));
|
|
var confidential = Doc("vertraulich"); confidential.IsConfidential = true; _docs.Add(confidential);
|
|
var draft = Doc("Entwurf"); draft.IsDraft = true; _docs.Add(draft);
|
|
var deleted = Doc("gelöscht"); deleted.IsDeleted = true; _docs.Add(deleted);
|
|
var otherGroup = Doc("fremdeGruppe"); otherGroup.GroupId = Guid.NewGuid(); _docs.Add(otherGroup);
|
|
var otherStudent = Doc("fremderSchüler"); otherStudent.StudentId = Guid.NewGuid(); _docs.Add(otherStudent);
|
|
var outside = Doc("außerhalb"); outside.Date = _date.AddDays(-1); _docs.Add(outside);
|
|
|
|
var text = Text((DrawingValue)Build()[StudentReportTemplate.Documentation]);
|
|
Assert.Contains("sichtbar", text);
|
|
foreach (var hidden in new[] { "vertraulich", "Entwurf", "gelöscht", "fremdeGruppe", "fremderSchüler", "außerhalb" })
|
|
Assert.DoesNotContain(hidden, text);
|
|
var included = Build(new(_date, _date, null, IncludeInterim: false, IncludeConfidential: true));
|
|
Assert.Contains("[Vertraulich]", Text((DrawingValue)included[StudentReportTemplate.Documentation]));
|
|
}
|
|
|
|
[Fact]
|
|
public void Zwischenstand_MussZumSchuelerZurGruppeUndZumZeitraumPassen()
|
|
{
|
|
var interim = new InterimGrade { StudentId = _student.Id, GroupId = _group.Id, Date = _date,
|
|
Occasion = "Sprechtag", OralValue = "2", WrittenValue = "3", OverallValue = "2-3" };
|
|
var values = Build(new(_date, _date, interim));
|
|
Assert.Contains("2-3", Text((DrawingValue)values[ReportTextDrawing.InterimGrades]));
|
|
interim.StudentId = Guid.NewGuid();
|
|
Assert.Throws<InvalidDataException>(() => Build(new(_date, _date, interim)));
|
|
interim.StudentId = _student.Id; interim.GroupId = Guid.NewGuid();
|
|
Assert.Throws<InvalidDataException>(() => Build(new(_date, _date, interim)));
|
|
interim.GroupId = _group.Id; interim.Date = _date.AddDays(1);
|
|
Assert.Throws<InvalidDataException>(() => Build(new(_date, _date, interim)));
|
|
}
|
|
|
|
[Fact]
|
|
public void AbgewaehlteBausteineBleibenLeer()
|
|
{
|
|
var values = Build(new(_date, _date, null, false, false, false, false, false));
|
|
Assert.All(StudentReportTemplate.Drawings, name => Assert.Empty(((DrawingValue)values[name]).Commands));
|
|
}
|
|
|
|
[Fact]
|
|
public void Hausaufgaben_AltdatenUndFremdeSitzungen()
|
|
{
|
|
var session = new ParticipationSession { GroupId = _group.Id, Date = _date };
|
|
_sessions.Add(session);
|
|
_entries.Add(new() { StudentId = _student.Id, SessionId = session.Id, HomeworkMissing = true });
|
|
_entries.Add(new() { StudentId = _student.Id, SessionId = Guid.NewGuid(), Homework = HomeworkStatus.Completed });
|
|
var text = Text((DrawingValue)Build()[StudentReportTemplate.Homework]);
|
|
Assert.Contains("Nicht gemacht", text);
|
|
Assert.DoesNotContain("Hausaufgabe gemacht", text);
|
|
}
|
|
|
|
[Fact]
|
|
public void Standardbericht_RenderbarMitGraphUndMehrseitigerDokumentation()
|
|
{
|
|
_aspects.Save(new() { Key = "quality", Label = "Qualität", Weight = 1 });
|
|
for (var i = 0; i < 4; i++)
|
|
{
|
|
var session = new ParticipationSession { GroupId = _group.Id, Date = _date.AddDays(i) };
|
|
_sessions.Add(session);
|
|
_entries.Add(new() { StudentId = _student.Id, SessionId = session.Id,
|
|
Ratings = [new() { Key = "quality", Value = i - 2 }], Homework = HomeworkStatus.Completed });
|
|
}
|
|
for (var i = 0; i < 55; i++) _docs.Add(new() { StudentId = _student.Id, GroupId = _group.Id,
|
|
Date = _date, Title = $"Eintrag {i:D2}", Content = "Lange Beobachtung mit einem ausführlichen Text über die regelmäßige Mitarbeit im Unterricht und die Lernfortschritte." });
|
|
var pdf = new QuestTemplateRenderer().RenderToPdf(StudentReportTemplate.Create(), new ReportProvider(Build()));
|
|
using var document = UglyToad.PdfPig.PdfDocument.Open(pdf);
|
|
Assert.True(document.NumberOfPages > 1);
|
|
Assert.All(document.GetPages(), page => Assert.Contains(_student.FullName.Replace(" ", ""), page.Text.Replace(" ", "")));
|
|
var text = string.Concat(document.GetPages().Select(p => p.Text)).Replace(" ", "");
|
|
Assert.Contains(_student.FullName.Replace(" ", ""), text);
|
|
Assert.Contains("Lerngruppe:9ChG", text);
|
|
Assert.Contains("GewichteteMitarbeit", text);
|
|
Assert.Contains("Eintrag54", text);
|
|
Assert.Contains("Lernfortschritte.", text);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Dialog_UngueltigeDatumsangabenErzeugenKeineDatei()
|
|
{
|
|
var directory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
|
|
try
|
|
{
|
|
var vm = new StudentReportDialogViewModel(_student,
|
|
new FakeMemberships([new() { StudentId = _student.Id, GroupId = _group.Id }]),
|
|
new FakeGroups([_group]), new FakeInterimGrades(), Service(), new QuestTemplateRenderer(),
|
|
new SchoolYearService(), [new TemplateStore(directory)]);
|
|
vm.From = "31.02.2026";
|
|
var output = Path.Combine(directory, "bericht.pdf");
|
|
Assert.False(await vm.GenerateAsync(output));
|
|
Assert.False(File.Exists(output));
|
|
Assert.Contains("TT.MM.JJJJ", vm.StatusMessage);
|
|
}
|
|
finally { if (Directory.Exists(directory)) Directory.Delete(directory, true); }
|
|
}
|
|
|
|
private sealed class ReportProvider(IReadOnlyDictionary<string, PlaceholderValue> values) : ITemplateDataProvider
|
|
{ public IReadOnlyDictionary<string, PlaceholderValue> GetValues() => values; }
|
|
|
|
private static string Text(DrawingValue drawing) => string.Join(" ", drawing.Commands.OfType<DrawStringEx>().Select(c => c.Text));
|
|
}
|