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 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); } }