fix: Sync-Statusanzeige zeigt nach Neustart fälschlich "nicht konfiguriert"

SyncEngine feuert sein erstes StatusChanged bereits im eigenen
Konstruktor. Da SyncEngine und SyncStatusViewModel beide DI-Singletons
sind und Letzterer Ersteren erst innerhalb der eigenen Factory aus dem
Container holt, lief dieser erste Broadcast ab, bevor
SyncStatusViewModel überhaupt abonniert hatte - der Status ging
verloren, StatusText blieb bis zum nächsten Auto-Sync oder manuellen
Sync beim hartcodierten Default "Kein Server konfiguriert".

Fix: Konstruktor ruft nach dem Abonnieren zusätzlich einmal
OnStatus(engine.Status) mit dem bereits vorhandenen aktuellen Zustand
auf. Regressionstest ergänzt - dabei fehlte LehrerApp.Desktop.Tests
das DisableTestParallelization-Attribut (gleicher bekannter
LiteDB-BsonMapper.Global-Bug wie in den anderen Testprojekten, sobald
zwei Testklassen parallel LiteDbContext konstruieren).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 01:14:22 +02:00
co-authored by Claude Sonnet 5
parent f8058b537b
commit 762c8236fe
4 changed files with 90 additions and 1 deletions
@@ -0,0 +1,62 @@
using LehrerApp.Data;
using LehrerApp.Desktop.ViewModels;
using LehrerApp.Sync;
using LehrerApp.Sync.Crypto;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class SyncStatusViewModelTests
{
[Fact]
public void Konstruktor_EngineBereitsVorhanden_ZeigtNichtDenNichtKonfiguriertText()
{
// SyncEngine feuert sein erstes StatusChanged schon im eigenen Konstruktor - läuft der vor
// dem Abonnieren in SyncStatusViewModel (z.B. weil beide DI-Singletons sind und
// GetService<SyncEngine>() den Engine-Konstruktor erst innerhalb der VM-Factory auslöst),
// ginge dieser erste Status verloren und StatusText bliebe fälschlich beim Default.
using var temp = new TempSyncEngine();
var vm = new SyncStatusViewModel(temp.Engine);
Assert.True(vm.IsServerConfigured);
Assert.NotEqual("Kein Server konfiguriert", vm.StatusText);
Assert.Equal("Synchronisiert", vm.StatusText);
}
[Fact]
public void Konstruktor_KeineEngine_ZeigtNichtKonfiguriertText()
{
var vm = new SyncStatusViewModel(null);
Assert.False(vm.IsServerConfigured);
Assert.Equal("Kein Server konfiguriert", vm.StatusText);
}
private sealed class TempSyncEngine : IDisposable
{
private readonly string _queuePath = Path.Combine(
Path.GetTempPath(), $"lehrerapp-desktop-tests-{Guid.NewGuid():N}.db");
private readonly LiteDbContext _db = new(new MemoryStream());
private readonly HttpClient _http = new();
public SyncEngine Engine { get; }
public TempSyncEngine()
{
var queue = new EventQueue(_queuePath);
var key = SyncCrypto.GenerateKey();
Engine = new SyncEngine(
queue, new ConflictResolver(queue), new EventApplier(_db, key),
new AttachmentSyncer(_db, _http, key), _http,
new SyncConfig { AutoSyncIntervalMinutes = 5 });
}
public void Dispose()
{
Engine.Dispose(); // disposed auch die EventQueue
_db.Dispose();
_http.Dispose();
if (File.Exists(_queuePath)) File.Delete(_queuePath);
}
}
}