Update-Pruefung regelmaessig und ab Werk an, Installation nur auf Klick
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:
@@ -368,6 +368,9 @@ namespace PolyTrader.App.Avalonia
|
||||
services.AddHostedService(sp => sp.GetRequiredService<WatchdogHeartbeatService>());
|
||||
services.AddHostedService(sp => sp.GetRequiredService<DeploymentcenterErrorReporter>());
|
||||
|
||||
// #587: regelmäßige Update-Prüfung mit Hinweis - installiert nie selbst.
|
||||
PolyTrader.Web.Updates.UpdateCheckServiceCollectionExtensions.AddPolyTraderUpdateCheck(services);
|
||||
|
||||
// Shell-Zustand (Fensterverwaltung). Auch im kopflosen Betrieb harmlos.
|
||||
services.AddSingleton<AvaloniaUiHost>();
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@ using PolyTrader.Core.Modularity;
|
||||
using PolyTrader.Core.Persistence;
|
||||
using PolyTrader.Core.Security;
|
||||
using PolyTrader.Modules.Supervisor.Persistence;
|
||||
using PolyTrader.Web.Updates;
|
||||
using PolyTraderSharp;
|
||||
using PolyTraderSharp.Models;
|
||||
using PolyTraderSharp.Services;
|
||||
@@ -51,8 +52,11 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
|
||||
private int _statusTicks;
|
||||
|
||||
/// <summary>Ergebnis der letzten Update-Prüfung – für den Klick auf „Jetzt installieren …".</summary>
|
||||
private UpdateCheckResult? _updateCheck;
|
||||
/// <summary>Fassung aus der letzten Update-Prüfung – für den Klick auf „Jetzt installieren …".</summary>
|
||||
private string? _updateVersion;
|
||||
|
||||
/// <summary>Mit „Später" ausgeblendete Fassung – das Banner kommt erst für eine noch neuere wieder.</summary>
|
||||
private string? _dismissedVersion;
|
||||
|
||||
public LauncherWindow() => AvaloniaXamlLoader.Load(this);
|
||||
|
||||
@@ -84,16 +88,25 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
|
||||
this.FindControl<Button>("btnInstallUpdate")!.Click += async (_, _) => await InstallUpdateAsync();
|
||||
this.FindControl<Button>("btnDismissUpdate")!.Click += (_, _) =>
|
||||
{
|
||||
_dismissedVersion = _updateVersion;
|
||||
this.FindControl<Border>("pnlUpdateBanner")!.IsVisible = false;
|
||||
};
|
||||
|
||||
_statusTimer.Tick += (_, _) => UpdateStatus();
|
||||
_statusTimer.Start();
|
||||
UpdateStatus();
|
||||
RefreshData();
|
||||
|
||||
// D-4: einmalige, stille Prüfung beim Start - fire-and-forget, darf den Start nie
|
||||
// verzögern oder blockieren. Nur aktiv, wenn Deploymentcenter:UpdateCheckEnabled gesetzt ist.
|
||||
_ = CheckForUpdateAsync();
|
||||
// #587: Geprüft wird regelmäßig im Hintergrund (UpdateCheckBackgroundService), hier nur angezeigt.
|
||||
// Bis zum 14.09.2026 prüfte diese Seite genau einmal beim Start - eine wochenlang laufende
|
||||
// Anwendung erfuhr nie von einem neuen Release. Kein Abmelden, siehe ThemeChanged unten.
|
||||
var updates = services.GetService<UpdateStatusService>();
|
||||
if (updates != null)
|
||||
{
|
||||
updates.Checked += OnUpdateChecked;
|
||||
if (updates.Last is { } last) OnUpdateChecked(last);
|
||||
}
|
||||
|
||||
// Die Umschalterflaechen werden im Code gesetzt und folgen dem Thema nicht von selbst.
|
||||
// Kein Abmelden: die Seite lebt in der Einfenster-Shell bis zum Programmende, ein
|
||||
@@ -185,56 +198,29 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
// ===== Update-Prüfung (D-4) =====
|
||||
|
||||
/// <summary>
|
||||
/// Prüft beim Start still auf ein neues Release. Installiert NIE automatisch (Leitentscheidung
|
||||
/// 4 aus dem Umsetzungsplan) - ein `is_critical`-Release ändert nur den Hinweistext, nicht das
|
||||
/// Verhalten. Wirft nie: ein nicht erreichbares Deploymentcenter darf den Start nicht stören.
|
||||
/// Zeigt das Ergebnis einer Hintergrundprüfung an. Installiert NIE automatisch (Leitentscheidung 4,
|
||||
/// bestätigt am 14.09.2026) - ein `is_critical`-Release ändert nur den Hinweistext, nicht das Verhalten.
|
||||
/// Kein Update, Fehler oder fehlende Lizenz blenden das Banner aus; die Einzelheiten stehen im WebUI
|
||||
/// unter Einstellungen → Version & Updates.
|
||||
/// </summary>
|
||||
private async Task CheckForUpdateAsync()
|
||||
private void OnUpdateChecked(UpdateCheckSnapshot snapshot)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dcOptions = _services.GetService<DeploymentcenterOptions>();
|
||||
if (dcOptions == null || !dcOptions.UpdateCheckEnabled || string.IsNullOrWhiteSpace(dcOptions.BaseUrl))
|
||||
return;
|
||||
|
||||
var settings = _services.GetService<ServerSettings>();
|
||||
string? licenseKey = null;
|
||||
try { licenseKey = SecretProtection.Unprotect(settings?.LicenseKey ?? string.Empty); }
|
||||
catch { /* nicht lesbarer Schlüssel -> Prüfung läuft ohne Zugangsdaten weiter */ }
|
||||
|
||||
var updateClient = new UpdateClient();
|
||||
var result = await updateClient.CheckForUpdateAsync(
|
||||
baseUrl: dcOptions.BaseUrl,
|
||||
projectId: dcOptions.ProjectSlug,
|
||||
currentVersion: BuildInfo.Version,
|
||||
channel: dcOptions.Channel,
|
||||
credentials: ReleaseCredentials.FromLicenseKey(licenseKey));
|
||||
|
||||
if (result.Unauthorized)
|
||||
{
|
||||
// Kein Netzwerkfehler: die Lizenz trägt nicht mehr für den Paketabruf. Kein
|
||||
// Alarm im Launcher nötig - die Lizenzprüfung selbst (D-2) hat das schon gemeldet.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.UpdateAvailable || result.LatestRelease == null) return;
|
||||
|
||||
_updateCheck = result;
|
||||
string version = result.LatestRelease.Version;
|
||||
string critical = result.IsCritical ? " (empfohlenes Sicherheitsupdate)" : "";
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
this.FindControl<TextBlock>("lblUpdateInfo")!.Text =
|
||||
$"Update verfügbar: v{version}{critical}. {result.LatestRelease.Changelog}".TrimEnd();
|
||||
this.FindControl<Border>("pnlUpdateBanner")!.IsVisible = true;
|
||||
});
|
||||
}
|
||||
catch
|
||||
var banner = this.FindControl<Border>("pnlUpdateBanner")!;
|
||||
if (!snapshot.UpdateAvailable || string.IsNullOrEmpty(snapshot.LatestVersion))
|
||||
{
|
||||
// Update-Prüfung darf den Start nie stören - stiller Rückzug, kein Log-Spam beim
|
||||
// vermutlich häufigsten Fall (Deploymentcenter nicht erreichbar).
|
||||
_updateVersion = null;
|
||||
banner.IsVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_updateVersion = snapshot.LatestVersion;
|
||||
string critical = snapshot.IsCritical ? " (empfohlenes Sicherheitsupdate)" : "";
|
||||
this.FindControl<TextBlock>("lblUpdateInfo")!.Text =
|
||||
$"Update verfügbar: v{snapshot.LatestVersion}{critical}. {snapshot.Changelog}".TrimEnd();
|
||||
banner.IsVisible = !string.Equals(_dismissedVersion, snapshot.LatestVersion, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -244,7 +230,7 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
/// </summary>
|
||||
private async Task InstallUpdateAsync()
|
||||
{
|
||||
if (_updateCheck?.LatestRelease == null) return;
|
||||
if (_updateVersion == null) return;
|
||||
|
||||
var dcOptions = _services.GetService<DeploymentcenterOptions>();
|
||||
if (dcOptions == null) return;
|
||||
@@ -259,7 +245,7 @@ namespace PolyTrader.App.Avalonia.Views
|
||||
}
|
||||
|
||||
bool confirmed = await DialogWindow.Confirm(this, "Update installieren",
|
||||
$"Version {_updateCheck.LatestRelease.Version} herunterladen und PolyTrader danach " +
|
||||
$"Version {_updateVersion} herunterladen und PolyTrader danach " +
|
||||
"neu starten?\n\nOffene Vorgänge werden dabei genauso geordnet beendet wie über „Beenden\".",
|
||||
"Installieren");
|
||||
if (!confirmed) return;
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
"WatchdogIntervalSeconds": 60,
|
||||
"WatchdogEnabled": false,
|
||||
"ErrorReportingEnabled": false,
|
||||
"UpdateCheckEnabled": false
|
||||
"_UpdateCheck_comment": "Prueft regelmaessig auf ein neues Release und weist darauf hin. Installiert wird nie automatisch, nur auf Klick im Desktop.",
|
||||
"UpdateCheckEnabled": true,
|
||||
"UpdateCheckIntervalHours": 6
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
|
||||
@@ -54,7 +54,14 @@ namespace PolyTrader.Core.Configuration
|
||||
/// <summary>Ungefangene Fehler an /api/errors/v1/report melden.</summary>
|
||||
public bool ErrorReportingEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>Beim Start auf ein neues Release prüfen (installiert nie automatisch).</summary>
|
||||
public bool UpdateCheckEnabled { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Regelmäßig auf ein neues Release prüfen und darauf hinweisen. Installiert nie automatisch - das
|
||||
/// geschieht nur auf Klick im Desktop. Ab Werk an (Richard, 14.09.2026, #587): Vorher stand hier
|
||||
/// <c>false</c>, und eine frisch installierte Anwendung erfuhr nie von einem neuen Release.
|
||||
/// </summary>
|
||||
public bool UpdateCheckEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>Abstand der Update-Prüfungen in Stunden, 1 bis 168.</summary>
|
||||
public int UpdateCheckIntervalHours { get; set; } = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,8 @@ namespace PolyTrader.Web.Hosting
|
||||
{
|
||||
services.AddSingleton(Options.Create(options));
|
||||
|
||||
// #565: Update-Status mit Zwischenspeicher - nicht jeder Seitenaufruf fragt das Deploymentcenter.
|
||||
services.AddSingleton<IUpdateChecker, DeploymentcenterUpdateChecker>();
|
||||
services.AddSingleton(sp => new UpdateStatusService(sp.GetRequiredService<IUpdateChecker>()));
|
||||
// Update-Status (#565) registriert Program.cs über AddPolyTraderUpdateCheck - unabhängig vom WebUI,
|
||||
// damit die regelmäßige Prüfung (#587) auch ohne WebUI läuft.
|
||||
});
|
||||
|
||||
hostBuilder.ConfigureWebHostDefaults(webBuilder =>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using PolyTrader.Core.Configuration;
|
||||
using PolyTraderSharp.Services;
|
||||
|
||||
namespace PolyTrader.Web.Updates
|
||||
{
|
||||
/// <summary>
|
||||
/// Prüft regelmäßig auf ein neues Release und weist darauf hin (#587).
|
||||
///
|
||||
/// <para><b>Installiert nie.</b> Richards Vorgabe vom 14.09.2026: Updates werden nicht automatisch
|
||||
/// eingespielt, die Prüfung mit Hinweis läuft aber von selbst. Installiert wird nur auf Klick im Desktop
|
||||
/// ("Jetzt installieren …"), weil das die Anwendung beendet.</para>
|
||||
///
|
||||
/// <para>Bis dahin prüfte der Desktop genau einmal beim Start und das WebUI nur, wenn jemand die Seite
|
||||
/// aufrief. Eine Anwendung, die wochenlang läuft - der Normalfall im Betrieb -, erfuhr so nie von einem
|
||||
/// neuen Release. Der Dienst läuft auch ohne WebUI und im kopflosen Betrieb; das Ergebnis landet im
|
||||
/// gemeinsamen <see cref="UpdateStatusService"/>, an dem Desktop-Banner und WebUI hängen.</para>
|
||||
/// </summary>
|
||||
public sealed class UpdateCheckBackgroundService : BackgroundService
|
||||
{
|
||||
/// <summary>Erste Prüfung kurz nach dem Start - nicht sofort, damit sie den Start nicht belastet.</summary>
|
||||
public static readonly TimeSpan StartDelay = TimeSpan.FromSeconds(30);
|
||||
|
||||
private readonly UpdateStatusService _status;
|
||||
private readonly TerminalLogger _logger;
|
||||
private readonly TimeSpan _interval;
|
||||
private string? _announcedVersion;
|
||||
|
||||
public UpdateCheckBackgroundService(UpdateStatusService status, TerminalLogger logger, DeploymentcenterOptions? options)
|
||||
{
|
||||
_status = status;
|
||||
_logger = logger;
|
||||
_interval = Interval(options);
|
||||
}
|
||||
|
||||
/// <summary>Takt aus <see cref="DeploymentcenterOptions.UpdateCheckIntervalHours"/>, auf 1 bis 168 Stunden begrenzt.</summary>
|
||||
public static TimeSpan Interval(DeploymentcenterOptions? options) =>
|
||||
TimeSpan.FromHours(Math.Clamp(options?.UpdateCheckIntervalHours ?? 6, 1, 168));
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(StartDelay, stoppingToken).ConfigureAwait(false);
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
await CheckOnceAsync(stoppingToken).ConfigureAwait(false);
|
||||
await Task.Delay(_interval, stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Herunterfahren
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eine Prüfung. Der Hinweis im Log erscheint einmal je neuer Fassung, nicht bei jeder Prüfung - sonst
|
||||
/// stünde dieselbe Zeile alle paar Stunden im Log, bis jemand installiert.
|
||||
/// </summary>
|
||||
public async Task CheckOnceAsync(CancellationToken ct)
|
||||
{
|
||||
var (snapshot, _, _) = await _status.GetAsync(force: false, ct).ConfigureAwait(false);
|
||||
if (!snapshot.UpdateAvailable || string.IsNullOrEmpty(snapshot.LatestVersion)) return;
|
||||
if (string.Equals(snapshot.LatestVersion, _announcedVersion, StringComparison.OrdinalIgnoreCase)) return;
|
||||
|
||||
_announcedVersion = snapshot.LatestVersion;
|
||||
string critical = snapshot.IsCritical ? " (empfohlenes Sicherheitsupdate)" : "";
|
||||
_logger.Info($"🔔 Update verfügbar: v{snapshot.LatestVersion}{critical}. Installiert wird nur auf Wunsch - " +
|
||||
"im Desktop über „Jetzt installieren …“ auf der Startseite.");
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateCheckServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Update-Prüfung für Desktop, WebUI und kopflosen Betrieb. Unabhängig davon, ob das WebUI läuft - bis
|
||||
/// zum 14.09.2026 hing die Registrierung am WebUI, ohne WebUI gab es keine regelmäßige Prüfung.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddPolyTraderUpdateCheck(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IUpdateChecker, DeploymentcenterUpdateChecker>();
|
||||
services.AddSingleton(sp => new UpdateStatusService(sp.GetRequiredService<IUpdateChecker>()));
|
||||
services.AddHostedService(sp => new UpdateCheckBackgroundService(
|
||||
sp.GetRequiredService<UpdateStatusService>(),
|
||||
sp.GetRequiredService<TerminalLogger>(),
|
||||
sp.GetService<DeploymentcenterOptions>()));
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,15 @@ namespace PolyTrader.Web.Updates
|
||||
_utcNow = utcNow ?? (() => DateTime.UtcNow);
|
||||
}
|
||||
|
||||
/// <summary>Letztes Prüfergebnis, <c>null</c> vor der ersten Prüfung.</summary>
|
||||
public UpdateCheckSnapshot? Last => _last;
|
||||
|
||||
/// <summary>
|
||||
/// Feuert nach jeder frischen Prüfung, nicht bei einer Antwort aus dem Zwischenspeicher. Der Desktop hängt
|
||||
/// sein Update-Banner daran - geprüft wird an genau einer Stelle, angezeigt an zweien.
|
||||
/// </summary>
|
||||
public event Action<UpdateCheckSnapshot>? Checked;
|
||||
|
||||
/// <summary>
|
||||
/// Liefert das Ergebnis, bei Bedarf frisch geprüft. <c>RetryAfter</c> ist gesetzt, wenn eine erzwungene
|
||||
/// Prüfung zu früh kam und stattdessen der vorige Stand geliefert wird.
|
||||
@@ -59,6 +68,7 @@ namespace PolyTrader.Web.Updates
|
||||
public async Task<(UpdateCheckSnapshot Snapshot, bool FromCache, TimeSpan? RetryAfter)> GetAsync(bool force, CancellationToken ct)
|
||||
{
|
||||
// Eine Prüfung zur Zeit: Gleichzeitige Aufrufe warten und bekommen danach das frische Ergebnis.
|
||||
UpdateCheckSnapshot fresh;
|
||||
await _gate.WaitAsync(ct);
|
||||
try
|
||||
{
|
||||
@@ -72,13 +82,17 @@ namespace PolyTrader.Web.Updates
|
||||
return (_last, true, MinManualInterval - age);
|
||||
}
|
||||
|
||||
_last = await _checker.CheckAsync(ct);
|
||||
return (_last, false, null);
|
||||
fresh = await _checker.CheckAsync(ct);
|
||||
_last = fresh;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_gate.Release();
|
||||
}
|
||||
|
||||
// Ausserhalb der Sperre: Ein Empfaenger, der selbst GetAsync ruft, soll sich nicht selbst blockieren.
|
||||
Checked?.Invoke(fresh);
|
||||
return (fresh, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
applyThemeChoice(currentThemeChoice());
|
||||
supChatWelcome = document.getElementById('supChatMessages')?.innerHTML ?? '';
|
||||
loadUpdateStatus(false); // #565: Banner im Dashboard; der Server haelt das Ergebnis vor
|
||||
// #587: Der Server prueft regelmaessig selbst; die Seite holt nur den vorgehaltenen Stand nach,
|
||||
// damit ein lange offenes Browserfenster ein neues Release auch mitbekommt.
|
||||
setInterval(() => loadUpdateStatus(false), 10 * 60 * 1000);
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === 'Escape' && document.getElementById('modalStopTrading')?.style.display === 'flex') closeStopTradingModal();
|
||||
});
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user