Files
ClaudeDo/tests/ClaudeDo.Installer.Tests/WizardViewModelTests.cs
T
mika kuns 09e0772673 feat(claude-do): „Claude Help Me"-Button: Claude-Session zur Setup-Fehlersuch
Der Button, der aus „Problem erkannt" ein „Problem gelöst" macht: startet eine interaktive Claude-Session, die dem Nutzer beim Einrichten hilft.

## Warum externes Terminal
Der ConPTY-Stack (`PtyTerminalSession`, `ConPtyPaneView`) liegt in `ClaudeDo.Ui` und ist Avalonia — der Installer ist WPF und referenziert nur Data/Releases/Localization. Beim Fresh Install sind `app\`/`worker\` außerdem noch n

ClaudeDo-Task: 4e196058-38a3-404f-9862-4cb0e90195da
2026-08-06 08:25:36 +02:00

88 lines
3.4 KiB
C#

using ClaudeDo.Installer.Checks;
using ClaudeDo.Installer.Core;
using ClaudeDo.Installer.Pages.InstallPage;
using ClaudeDo.Installer.Pages.PathsPage;
using ClaudeDo.Installer.Pages.ServicePage;
using ClaudeDo.Installer.Pages.SystemCheckPage;
using ClaudeDo.Installer.Pages.UiSettingsPage;
using ClaudeDo.Installer.Pages.WelcomePage;
using ClaudeDo.Installer.Tests.Core;
using ClaudeDo.Installer.Tests.Pages.SystemCheckPage;
using ClaudeDo.Installer.Views;
using Microsoft.Extensions.DependencyInjection;
namespace ClaudeDo.Installer.Tests;
public class WizardViewModelTests
{
private static IReadOnlyList<IInstallerPage> BuildAllPages(InstallContext context)
{
var emptyServiceProvider = new ServiceCollection().BuildServiceProvider();
return new IInstallerPage[]
{
new WelcomePageViewModel(context),
new SystemCheckPageViewModel(context, () => throw new InvalidOperationException("not needed for this test"), TestClaudeHelpLauncher.Create()),
new PathsPageViewModel(context),
new ServicePageViewModel(context),
new UiSettingsPageViewModel(context),
new InstallPageViewModel(context, emptyServiceProvider),
};
}
[Fact]
public void FreshInstall_includes_SystemCheckPage_directly_after_welcome()
{
var context = new InstallContext { Mode = InstallerMode.FreshInstall };
var resolver = new PageResolver(BuildAllPages(context));
var vm = new WizardViewModel(resolver, context, new FakeLocalizer());
var pages = vm.Pages.ToList();
var welcomeIndex = pages.FindIndex(p => p is WelcomePageViewModel);
var systemCheckIndex = pages.FindIndex(p => p is SystemCheckPageViewModel);
Assert.NotEqual(-1, welcomeIndex);
Assert.Equal(welcomeIndex + 1, systemCheckIndex);
}
[Fact]
public void Update_mode_does_not_show_SystemCheckPage()
{
var context = new InstallContext { Mode = InstallerMode.Update };
var resolver = new PageResolver(BuildAllPages(context));
var vm = new WizardViewModel(resolver, context, new FakeLocalizer());
Assert.DoesNotContain(vm.Pages, p => p is SystemCheckPageViewModel);
}
[Fact]
public async Task CanGoNext_is_false_while_the_system_check_page_has_a_blocking_error_and_true_after_a_clean_recheck()
{
var context = new InstallContext { Mode = InstallerMode.FreshInstall };
var callNumber = 0;
var systemCheckPage = new SystemCheckPageViewModel(context, () =>
{
callNumber++;
IEnvironmentCheck check = callNumber == 1
? FakeEnvironmentCheck.Fail("git", CheckSeverity.Error)
: FakeEnvironmentCheck.Ok("git");
return new EnvironmentCheckService(new[] { check });
}, TestClaudeHelpLauncher.Create());
var resolver = new PageResolver(new IInstallerPage[]
{
new WelcomePageViewModel(context),
systemCheckPage,
});
var vm = new WizardViewModel(resolver, context, new FakeLocalizer());
await vm.GoNextCommand.ExecuteAsync(null); // Welcome -> SystemCheck; auto-run fails
Assert.Same(systemCheckPage, vm.CurrentPage);
Assert.False(vm.CanGoNext);
await systemCheckPage.RunChecksCommand.ExecuteAsync(null); // recheck comes back clean
Assert.True(vm.CanGoNext);
}
}