Files
SilverMetal/windows/welcome/tests/SilverOS.Welcome.Tests/ApplyStepTests.cs
sysadmin ea5adacac3 feat(welcome): apply step wiring + Mercury styling
Wire ApplyStep with public StartAsync(), IProgress<ApplyProgress> marshalled
via InvokeAsync(StateHasChanged), OnComplete EventCallback (host advances to
Done), and failure surface + Retry button. Add _Imports.razor Apply using.
Wire Routes.razor AdvanceToDone handler. Add Mercury CSS: slate-void palette,
DM Mono typography, layered radial gradients, staggered step-enter animation,
styled wizard chrome/cards/fields/progress bar/buttons. 17/17 tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 03:20:39 +01:00

73 lines
3.0 KiB
C#

using Bunit;
using Moq;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using SilverOS.Welcome.App.Components;
using SilverOS.Welcome.App.Components.Steps;
using SilverOS.Welcome.Core.Apply;
using SilverOS.Welcome.Core.Flavours;
using Xunit;
public class ApplyStepTests : TestContext
{
[Fact]
public async Task Calls_apply_with_the_wizard_selections()
{
var apply = new Mock<IApplyService>();
var state = new WizardState
{
Flavour = new FlavourManifest { Id = "daily-driver", Hardening = new() { Modules = new[] { "00" } } },
Username = "alice",
Password = "pw",
AdminPassword = "apw",
BitLockerPin = "123456"
};
Services.AddSingleton(state);
Services.AddSingleton(apply.Object);
var cut = RenderComponent<ApplyStep>();
await cut.InvokeAsync(() => cut.Instance.StartAsync());
apply.Verify(a => a.RunAsync(
It.Is<ApplyRequest>(r => r.Username == "alice" && r.Flavour.Id == "daily-driver"),
It.IsAny<IProgress<ApplyProgress>>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task OnComplete_invoked_when_apply_succeeds()
{
var apply = new Mock<IApplyService>();
apply.Setup(a => a.RunAsync(It.IsAny<ApplyRequest>(), It.IsAny<IProgress<ApplyProgress>>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
var state = new WizardState
{
Flavour = new FlavourManifest { Id = "daily-driver", Hardening = new() { Modules = new[] { "00" } } },
Username = "alice", Password = "pw", AdminPassword = "apw", BitLockerPin = "123456"
};
Services.AddSingleton(state);
Services.AddSingleton(apply.Object);
var completed = false;
var cut = RenderComponent<ApplyStep>(p => p.Add(s => s.OnComplete, EventCallback.Factory.Create(this, () => { completed = true; })));
await cut.InvokeAsync(() => cut.Instance.StartAsync());
Assert.True(completed);
}
[Fact]
public async Task Shows_error_and_retry_button_when_apply_fails()
{
var apply = new Mock<IApplyService>();
apply.Setup(a => a.RunAsync(It.IsAny<ApplyRequest>(), It.IsAny<IProgress<ApplyProgress>>(), It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException("Module 03 failed"));
var state = new WizardState
{
Flavour = new FlavourManifest { Id = "daily-driver", Hardening = new() { Modules = new[] { "00" } } },
Username = "alice", Password = "pw", AdminPassword = "apw", BitLockerPin = "123456"
};
Services.AddSingleton(state);
Services.AddSingleton(apply.Object);
var cut = RenderComponent<ApplyStep>();
await cut.InvokeAsync(() => cut.Instance.StartAsync());
Assert.Contains("Module 03 failed", cut.Markup);
Assert.NotNull(cut.Find(".btn-retry"));
}
}