This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using System.IO.Compression;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Core.Services;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
using LehrerApp.Templating;
|
||||
using Xunit;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
@@ -9,16 +8,12 @@ namespace LehrerApp.Desktop.Tests;
|
||||
public sealed class CreateLetterDialogViewModelTests : IDisposable
|
||||
{
|
||||
private readonly string _directory = Path.Combine(Path.GetTempPath(), $"lehrerapp-letter-vm-tests-{Guid.NewGuid():N}");
|
||||
|
||||
public CreateLetterDialogViewModelTests() => Directory.CreateDirectory(_directory);
|
||||
|
||||
[Fact]
|
||||
public void OhneVorlage_KannKeinenBriefErzeugen()
|
||||
{
|
||||
var student = StudentWithContact("Sehr geehrte Frau Muster,");
|
||||
|
||||
var vm = Build(student, new LetterTemplateService(_directory));
|
||||
|
||||
var vm = Build(StudentWithContact("Sehr geehrte Frau Muster,"), new TemplateStore(_directory));
|
||||
Assert.False(vm.CanGenerate);
|
||||
Assert.Contains(vm.Issues, i => i.Message.Contains("Vorlage", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
@@ -26,83 +21,50 @@ public sealed class CreateLetterDialogViewModelTests : IDisposable
|
||||
[Fact]
|
||||
public void VerwendeteBriefanredeFehlt_BlockiertErzeugung()
|
||||
{
|
||||
var service = ServiceWithTemplate("Letter.Salutation");
|
||||
var vm = Build(StudentWithContact(null), service);
|
||||
|
||||
var vm = Build(StudentWithContact(null), StoreWithTemplate(
|
||||
new PlaceholderDefinition("Anrede", PlaceholderType.Text, true)));
|
||||
Assert.False(vm.CanGenerate);
|
||||
Assert.Contains(vm.Issues, i => i.Message.Contains("Briefanrede"));
|
||||
Assert.Contains(vm.Issues, i => i.Message.Contains("Anrede", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VollstaendigeDaten_ErzeugenEditierbareDocxKopie()
|
||||
public void VollstaendigeDaten_ErzeugenFlachesPdf()
|
||||
{
|
||||
var service = ServiceWithTemplate("Letter.Salutation", "Student.FirstName", "CurrentDate");
|
||||
var vm = Build(StudentWithContact("Sehr geehrte Frau Muster,"), service);
|
||||
var output = Path.Combine(_directory, "Brief.docx");
|
||||
var store = StoreWithTemplate(new PlaceholderDefinition("Anrede", PlaceholderType.Text, true),
|
||||
new PlaceholderDefinition("Datum", PlaceholderType.Date, true),
|
||||
new PlaceholderDefinition("Brieftext", PlaceholderType.Multiline, true));
|
||||
var vm = Build(StudentWithContact("Sehr geehrte Frau Muster,"), store);
|
||||
vm.LetterText = "Dies ist der Inhalt.";
|
||||
var output = Path.Combine(_directory, "Brief.pdf");
|
||||
|
||||
var generated = vm.Generate(output);
|
||||
|
||||
Assert.True(generated);
|
||||
Assert.True(File.Exists(output));
|
||||
using var archive = ZipFile.OpenRead(output);
|
||||
using var reader = new StreamReader(archive.GetEntry("word/document.xml")!.Open());
|
||||
var xml = reader.ReadToEnd();
|
||||
Assert.Contains("Sehr geehrte Frau Muster,", xml);
|
||||
Assert.Contains("Lena", xml);
|
||||
Assert.True(vm.Generate(output));
|
||||
Assert.Equal("%PDF", System.Text.Encoding.ASCII.GetString(File.ReadAllBytes(output), 0, 4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KontaktBearbeiten_SpeichertExpliziteBriefanrede()
|
||||
private CreateLetterDialogViewModel Build(Student student, TemplateStore store) =>
|
||||
new(student, store, new QuestTemplateRenderer(), new FakeMemberships([]), new FakeGroups([]));
|
||||
|
||||
private TemplateStore StoreWithTemplate(params PlaceholderDefinition[] definitions)
|
||||
{
|
||||
var vm = new ContactEditDialogViewModel(new Contact { Name = "Frau Muster" });
|
||||
vm.LetterSalutation = "Sehr geehrte Frau Muster,";
|
||||
|
||||
vm.SaveCommand.Execute(null);
|
||||
|
||||
Assert.Equal("Sehr geehrte Frau Muster,", vm.Result!.LetterSalutation);
|
||||
}
|
||||
|
||||
private CreateLetterDialogViewModel Build(Student student, LetterTemplateService service) =>
|
||||
new(student, service, new FakeMemberships([]), new FakeGroups([]));
|
||||
|
||||
private LetterTemplateService ServiceWithTemplate(params string[] tags)
|
||||
{
|
||||
var source = Path.Combine(_directory, $"{Guid.NewGuid():N}.docx");
|
||||
using (var archive = ZipFile.Open(source, ZipArchiveMode.Create))
|
||||
var source = Path.Combine(_directory, $"{Guid.NewGuid():N}.lavorlage");
|
||||
var manifest = new TemplateManifest { Id = $"brief-{Guid.NewGuid():N}", Name = "Elternbrief", Placeholders = [.. definitions] };
|
||||
var lines = new List<string> { "PAGE 210 297 mm" };
|
||||
var y = 20;
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
var entry = archive.CreateEntry("word/document.xml");
|
||||
using var writer = new StreamWriter(entry.Open());
|
||||
var controls = string.Join("", tags.Select(tag =>
|
||||
$"<w:sdt><w:sdtPr><w:tag w:val=\"{tag}\"/></w:sdtPr><w:sdtContent>" +
|
||||
"<w:p><w:r><w:t>Platzhalter</w:t></w:r></w:p></w:sdtContent></w:sdt>"));
|
||||
writer.Write("<w:document xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">" +
|
||||
$"<w:body>{controls}</w:body></w:document>");
|
||||
var element = definition.Type == PlaceholderType.Multiline ? "TEXTBOX" : "TEXT";
|
||||
lines.Add(element == "TEXTBOX" ? $"TEXTBOX 20 {y} 170 80 ${definition.Name}" : $"TEXT 20 {y} ${definition.Name}");
|
||||
y += 20;
|
||||
}
|
||||
var service = new LetterTemplateService(Path.Combine(_directory, $"service-{Guid.NewGuid():N}"));
|
||||
service.Import(source, "Elternbrief");
|
||||
return service;
|
||||
TemplatePackage.Create(source, manifest, string.Join('\n', lines), new Dictionary<string, byte[]>());
|
||||
var store = new TemplateStore(Path.Combine(_directory, $"store-{Guid.NewGuid():N}")); store.Import(source); return store;
|
||||
}
|
||||
|
||||
private static Student StudentWithContact(string? salutation) => new()
|
||||
{
|
||||
FirstName = "Lena",
|
||||
LastName = "Beispiel",
|
||||
Contacts =
|
||||
[
|
||||
new Contact
|
||||
{
|
||||
Name = "Frau Muster",
|
||||
Relation = "Mutter",
|
||||
LetterSalutation = salutation,
|
||||
Street = "Hauptstraße 1",
|
||||
PostalCode = "12345",
|
||||
City = "Musterstadt",
|
||||
},
|
||||
],
|
||||
FirstName = "Lena", LastName = "Beispiel",
|
||||
Contacts = [new Contact { Name = "Frau Muster", Relation = "Mutter", LetterSalutation = salutation,
|
||||
Street = "Hauptstraße 1", PostalCode = "12345", City = "Musterstadt" }],
|
||||
};
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_directory)) Directory.Delete(_directory, recursive: true);
|
||||
}
|
||||
public void Dispose() { if (Directory.Exists(_directory)) Directory.Delete(_directory, true); }
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using LehrerApp.Sync;
|
||||
using LehrerApp.Sync.Models;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
using LehrerApp.Templating;
|
||||
|
||||
namespace LehrerApp.Desktop.Tests;
|
||||
|
||||
@@ -34,7 +35,7 @@ public sealed class SettingsViewModelTests
|
||||
new FakeDocumentation(), new FakeStudents([]), new FakeShorthandCodes([]),
|
||||
holidays ?? new FakeSchoolHolidays(), new SchoolCalendarSettingsService(tempPath),
|
||||
new PeriodScheduleService(tempPath), supervisionDuties ?? new FakeSupervisionDuties(),
|
||||
new LetterTemplateService(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
new TemplateStore(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
TestSupport.BuildWebUntisSettingsService(),
|
||||
TestSupport.BuildAnnualPlanSettingsService(),
|
||||
TestSupport.BuildSyncSettingsService(), TestSupport.BuildSyncAuthService(),
|
||||
@@ -320,7 +321,7 @@ public sealed class SettingsViewModelTests
|
||||
new LiteDbContext(new MemoryStream()), new PrivacySettingsService(tempPath),
|
||||
new FakeDocumentation(), new FakeStudents([]), new FakeShorthandCodes([]),
|
||||
new FakeSchoolHolidays(), calendarSettings, new PeriodScheduleService(tempPath),
|
||||
new FakeSupervisionDuties(), new LetterTemplateService(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
new FakeSupervisionDuties(), new TemplateStore(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
TestSupport.BuildWebUntisSettingsService(),
|
||||
TestSupport.BuildAnnualPlanSettingsService(),
|
||||
TestSupport.BuildSyncSettingsService(), TestSupport.BuildSyncAuthService(), TestSupport.BuildEventQueue(),
|
||||
@@ -348,7 +349,7 @@ public sealed class SettingsViewModelTests
|
||||
new LiteDbContext(new MemoryStream()), new PrivacySettingsService(tempPath),
|
||||
new FakeDocumentation(), new FakeStudents([]), new FakeShorthandCodes([]),
|
||||
new FakeSchoolHolidays(), new SchoolCalendarSettingsService(tempPath), periodSchedule,
|
||||
new FakeSupervisionDuties(), new LetterTemplateService(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
new FakeSupervisionDuties(), new TemplateStore(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
TestSupport.BuildWebUntisSettingsService(),
|
||||
TestSupport.BuildAnnualPlanSettingsService(),
|
||||
TestSupport.BuildSyncSettingsService(), TestSupport.BuildSyncAuthService(), TestSupport.BuildEventQueue(),
|
||||
@@ -380,7 +381,7 @@ public sealed class SettingsViewModelTests
|
||||
new LiteDbContext(new MemoryStream()), new PrivacySettingsService(tempPath),
|
||||
new FakeDocumentation(), new FakeStudents([]), new FakeShorthandCodes([]),
|
||||
new FakeSchoolHolidays(), new SchoolCalendarSettingsService(tempPath), periodSchedule,
|
||||
new FakeSupervisionDuties(), new LetterTemplateService(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
new FakeSupervisionDuties(), new TemplateStore(tempPath), TestSupport.BuildAiSettingsService(), TestSupport.BuildAiPlanningService(),
|
||||
TestSupport.BuildWebUntisSettingsService(),
|
||||
TestSupport.BuildAnnualPlanSettingsService(),
|
||||
TestSupport.BuildSyncSettingsService(), TestSupport.BuildSyncAuthService(), TestSupport.BuildEventQueue(),
|
||||
|
||||
Reference in New Issue
Block a user