Update-Pruefung regelmaessig und ab Werk an, Installation nur auf Klick
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s

Richards Vorgabe vom 14.09.2026 (#587): Updates nie automatisch installieren,
aber regelmaessig pruefen und darauf hinweisen.

Bisher pruefte der Desktop genau einmal beim Start, das WebUI nur beim
Seitenaufruf, und ab Werk gar nicht (UpdateCheckEnabled=false). Eine
wochenlang laufende oder frisch installierte Anwendung erfuhr nie von einem
neuen Release.

- UpdateCheckEnabled ab Werk true, neu UpdateCheckIntervalHours (6, 1..168)
- UpdateCheckBackgroundService: erste Pruefung nach 30 s, dann im Takt; laeuft
  auch ohne WebUI und kopflos; Hinweis im Log einmal je neuer Fassung
- Registrierung ueber AddPolyTraderUpdateCheck, nicht mehr am WebUI
- Desktop-Banner haengt an UpdateStatusService.Checked; "Spaeter" blendet bis
  zur naechsten neueren Fassung aus
- WebUI-Banner holt alle 10 Minuten den vorgehaltenen Stand

Auf der Linux-VM geprueft: 0.1.9 ohne Handeinstellung erkennt 0.2.0, ein
Hinweis im Log, Banner erscheint, "Spaeter" blendet aus, Beenden in 0,1 s.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-09-14 12:16:33 +02:00
co-authored by Claude Opus 5
parent 14c89aea7d
commit b4d8a2a647
9 changed files with 241 additions and 58 deletions
@@ -104,6 +104,80 @@ namespace PolyTrader.Tests.WebUi
Assert.Equal(1, checker.Calls);
}
[Fact]
public async Task Checked_feuert_nur_bei_frischer_Pruefung()
{
var clock = new Clock();
var checker = new FakeChecker(() => clock.Now);
var service = new UpdateStatusService(checker, () => clock.Now);
int events = 0;
service.Checked += _ => events++;
await service.GetAsync(false, CancellationToken.None);
await service.GetAsync(false, CancellationToken.None); // aus dem Zwischenspeicher
Assert.Equal(1, events);
Assert.Equal("0.2.0", service.Last?.LatestVersion);
}
[Fact]
public async Task Hintergrundpruefung_meldet_jede_neue_Fassung_genau_einmal_und_installiert_nichts()
{
var clock = new Clock();
var checker = new FakeChecker(() => clock.Now);
var status = new UpdateStatusService(checker, () => clock.Now);
var logger = new PolyTraderSharp.Services.TerminalLogger();
var notices = new System.Collections.Generic.List<string>();
logger.OnLogMessage += (_, e) => { if (e.Message.Contains("Update verfügbar")) notices.Add(e.Message); };
var background = new UpdateCheckBackgroundService(status, logger, null);
await background.CheckOnceAsync(CancellationToken.None);
clock.Now = clock.Now + UpdateStatusService.CacheDuration;
await background.CheckOnceAsync(CancellationToken.None); // dieselbe Fassung: kein zweiter Hinweis
checker.Result = checker.Result with { LatestVersion = "0.3.0" };
clock.Now = clock.Now + UpdateStatusService.CacheDuration;
await background.CheckOnceAsync(CancellationToken.None);
Assert.Equal(2, notices.Count);
Assert.Contains("v0.2.0", notices[0]);
Assert.Contains("v0.3.0", notices[1]);
Assert.All(notices, n => Assert.Contains("nur auf Wunsch", n));
}
[Fact]
public async Task Ohne_Update_kein_Hinweis()
{
var clock = new Clock();
var checker = new FakeChecker(() => clock.Now);
checker.Result = checker.Result with { UpdateAvailable = false, LatestVersion = null };
var logger = new PolyTraderSharp.Services.TerminalLogger();
int notices = 0;
logger.OnLogMessage += (_, e) => { if (e.Message.Contains("Update verfügbar")) notices++; };
await new UpdateCheckBackgroundService(new UpdateStatusService(checker, () => clock.Now), logger, null)
.CheckOnceAsync(CancellationToken.None);
Assert.Equal(0, notices);
}
[Theory]
[InlineData(null, 6)]
[InlineData(0, 1)]
[InlineData(12, 12)]
[InlineData(10000, 168)]
public void Pruefintervall_ist_begrenzt(int? hours, int expected)
{
var options = hours == null ? null : new PolyTrader.Core.Configuration.DeploymentcenterOptions { UpdateCheckIntervalHours = hours.Value };
Assert.Equal(TimeSpan.FromHours(expected), UpdateCheckBackgroundService.Interval(options));
}
[Fact]
public void Update_Pruefung_ist_ab_Werk_an()
{
Assert.True(new PolyTrader.Core.Configuration.DeploymentcenterOptions().UpdateCheckEnabled);
}
[Fact]
public async Task Route_liefert_Fassung_Stand_und_verweist_zur_Installation_auf_den_Desktop()
{