feat: Web-UI als zweiter Ausgabeweg neben Avalonia-Shell (#490)
- Einheitlicher WebserverWorker in IBKRTrader.Hosting auf Kestrel-Basis - Token-Authentifizierung (AuthService) mit zeitkonstantem Vergleich und HMAC-Session-Tokens - OrderManager im Core fuer Bestands- und Reservierungsabgleich offener Broker-Orders - SettingsSchema fuer reflexionsbasiertes Auslesen und sichere Aktualisierung ohne Klartext-Passwoerter - SSE-Streaming (LogStreamService) fuer Echtzeit-Logs ueber isolierte Channels - Statische Single-Page-Application in wwwroot (Avalonia Fluent / Polytrader Theme) fuer alle 9 Ansichten - Unit-Tests fuer OrderManager, AuthService, SettingsSchema, LogStreamService und WebserverWorker (498 Tests gruen)
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
using FluentAssertions;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using IBKRTrader.Core.Settings;
|
||||
using IBKRTrader.Core.Workers;
|
||||
using IBKRTrader.Hosting.Web;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NSubstitute;
|
||||
|
||||
namespace IBKRTrader.Tests.Web;
|
||||
|
||||
[Trait("cat", "unit")]
|
||||
public class WebserverWorkerTests
|
||||
{
|
||||
private sealed class InMemoryFactory : IDbContextFactory<CoreDbContext>
|
||||
{
|
||||
private readonly DbContextOptions<CoreDbContext> _options;
|
||||
public InMemoryFactory(DbContextOptions<CoreDbContext> options) => _options = options;
|
||||
public CoreDbContext CreateDbContext() => new(_options);
|
||||
}
|
||||
|
||||
private static (WebserverWorker Sut, SettingsService Settings) CreateSut(bool enabled = true, int port = 5001)
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<CoreDbContext>()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
var dbf = new InMemoryFactory(options);
|
||||
var settings = new SettingsService();
|
||||
settings.Settings.Webserver.Enabled = enabled;
|
||||
settings.Settings.Webserver.Port = port;
|
||||
|
||||
var logger = new LoggingService();
|
||||
var sp = Substitute.For<IServiceProvider>();
|
||||
|
||||
var sut = new WebserverWorker(logger, dbf, settings, sp);
|
||||
return (sut, settings);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Worker_Properties_AreConfiguredCorrectly()
|
||||
{
|
||||
var (sut, _) = CreateSut(enabled: true, port: 5001);
|
||||
|
||||
sut.Name.Should().Be("WebserverService");
|
||||
sut.Module.Should().Be("Core");
|
||||
sut.Type.Should().Be(WorkerType.Service);
|
||||
sut.Info.Active.Should().BeTrue();
|
||||
sut.Info.RunEvery.Should().Be("Service");
|
||||
sut.Info.Info.Should().Be("Port 5001");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Worker_WhenDisabled_ReportsInactive()
|
||||
{
|
||||
var (sut, _) = CreateSut(enabled: false, port: 8080);
|
||||
|
||||
sut.Info.Active.Should().BeFalse();
|
||||
sut.Info.Info.Should().Be("Deaktiviert");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user