From 0bc26f1e62275e69d4a10d9bf14a20b81646188f Mon Sep 17 00:00:00 2001 From: laurentiu021 Date: Mon, 8 Jun 2026 14:17:50 +0300 Subject: [PATCH] test: fix IntegrationTests compile drift and add CI compile-check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IntegrationTests project had accumulated 64 compile errors because it was never built in CI, so ViewModel/service signature changes silently broke it: - WindowsUpdateViewModel ctor gained a WindowsUpdateService param (#611) - DashboardViewModel ctor gained a TemperatureService param - LogsViewModel.SearchText was renamed to FilterText - DashboardViewModel.Snapshot/CpuLine/MemLine and RequestElevationCommand, WindowsUpdateViewModel.ListFeatureUpdatesCommand were removed/renamed Updated all constructors and rewrote the tests that referenced removed API to assert the current surface. Added a 'Build integration tests (compile check)' step to ci.yml (restore + build only — not run in CI since they touch the live system) so this drift is caught immediately from now on. No production code changed; no release. --- .github/workflows/ci.yml | 7 ++++ .../AdminElevationVmTests.cs | 6 ++-- .../AllViewModelsSweepTests.cs | 6 ++-- .../DashboardViewModelTests.cs | 36 ++++++++++++------- .../LightTouchViewModelTests.cs | 13 +++---- .../LogsViewModelExtendedTests.cs | 16 ++++----- .../QaResilienceTests.cs | 2 +- .../WindowsUpdateAutoCheckTests.cs | 2 +- .../WindowsUpdateViewModelTests.cs | 6 ++-- 9 files changed, 56 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dcc8629..b4b8757 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,7 @@ jobs: run: | dotnet restore SysManager/SysManager/SysManager.csproj dotnet restore SysManager/SysManager.Tests/SysManager.Tests.csproj + dotnet restore SysManager/SysManager.IntegrationTests/SysManager.IntegrationTests.csproj dotnet restore SysManager/SysManager.UITests/SysManager.UITests.csproj - name: Check formatting @@ -51,6 +52,12 @@ jobs: - name: Build tests run: dotnet build SysManager/SysManager.Tests/SysManager.Tests.csproj -c Release --no-restore + # Compile-check the integration tests so ViewModel/service signature drift is + # caught in CI. They are NOT run here (they touch the live system); compilation + # alone catches the constructor/property mismatches that previously slipped by. + - name: Build integration tests (compile check) + run: dotnet build SysManager/SysManager.IntegrationTests/SysManager.IntegrationTests.csproj -c Release --no-restore + - name: Run unit tests run: > dotnet test SysManager/SysManager.Tests/SysManager.Tests.csproj diff --git a/SysManager/SysManager.IntegrationTests/AdminElevationVmTests.cs b/SysManager/SysManager.IntegrationTests/AdminElevationVmTests.cs index ea229f5..a861005 100644 --- a/SysManager/SysManager.IntegrationTests/AdminElevationVmTests.cs +++ b/SysManager/SysManager.IntegrationTests/AdminElevationVmTests.cs @@ -16,7 +16,7 @@ public class AdminElevationVmTests [Fact] public void WindowsUpdateVm_ExposesIsElevated() { - var vm = new WindowsUpdateViewModel(new PowerShellRunner()); + var vm = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()); // Must equal the current process' elevation state. Assert.Equal(Helpers.AdminHelper.IsElevated(), vm.IsElevated); } @@ -24,7 +24,7 @@ public void WindowsUpdateVm_ExposesIsElevated() [Fact] public void WindowsUpdateVm_HasRelaunchCommand() { - var vm = new WindowsUpdateViewModel(new PowerShellRunner()); + var vm = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()); Assert.NotNull(vm.RelaunchAsAdminCommand); } @@ -59,7 +59,7 @@ public void AppUpdatesVm_HasRelaunchCommand() [Fact] public void AllElevationVms_Report_SameElevationFlag() { - var a = new WindowsUpdateViewModel(new PowerShellRunner()).IsElevated; + var a = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()).IsElevated; var b = new CleanupViewModel(new PowerShellRunner()).IsElevated; var c = new AppUpdatesViewModel(new WingetService(new PowerShellRunner())).IsElevated; Assert.Equal(a, b); diff --git a/SysManager/SysManager.IntegrationTests/AllViewModelsSweepTests.cs b/SysManager/SysManager.IntegrationTests/AllViewModelsSweepTests.cs index a46e3ba..dcba823 100644 --- a/SysManager/SysManager.IntegrationTests/AllViewModelsSweepTests.cs +++ b/SysManager/SysManager.IntegrationTests/AllViewModelsSweepTests.cs @@ -16,9 +16,9 @@ namespace SysManager.IntegrationTests; [Collection("Network")] public class AllViewModelsSweepTests { - [Fact] public void Dashboard_Constructs() => Assert.NotNull(new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService()))); + [Fact] public void Dashboard_Constructs() => Assert.NotNull(new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService()), new TemperatureService(new DiskHealthService(), skipHardwareInit: true))); [Fact] public void AppUpdates_Constructs() => Assert.NotNull(new AppUpdatesViewModel(new WingetService(new PowerShellRunner()))); - [Fact] public void WindowsUpdate_Constructs() => Assert.NotNull(new WindowsUpdateViewModel(new PowerShellRunner())); + [Fact] public void WindowsUpdate_Constructs() => Assert.NotNull(new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService())); [Fact] public void SystemHealth_Constructs() => Assert.NotNull(new SystemHealthViewModel(new SystemInfoService(), new DiskHealthService(), new MemoryTestService(), new FixedDriveService(), new PowerShellRunner())); [Fact] public void Cleanup_Constructs() => Assert.NotNull(new CleanupViewModel(new PowerShellRunner())); [Fact] public void DeepCleanup_Constructs() => Assert.NotNull(new DeepCleanupViewModel(new DeepCleanupService(), new LargeFileScanner(), new FixedDriveService())); @@ -28,7 +28,7 @@ public class AllViewModelsSweepTests [Fact] public void MainWindow_Constructs() => Assert.NotNull(new MainWindowViewModel()); [Fact] public void Dashboard_HasNonEmptySummaryOrEmpty() - => Assert.NotNull(new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService()))); + => Assert.NotNull(new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService()), new TemperatureService(new DiskHealthService(), skipHardwareInit: true))); [Fact] public void AppUpdates_HasCollections() { diff --git a/SysManager/SysManager.IntegrationTests/DashboardViewModelTests.cs b/SysManager/SysManager.IntegrationTests/DashboardViewModelTests.cs index 4396f60..b4853ad 100644 --- a/SysManager/SysManager.IntegrationTests/DashboardViewModelTests.cs +++ b/SysManager/SysManager.IntegrationTests/DashboardViewModelTests.cs @@ -10,10 +10,21 @@ namespace SysManager.IntegrationTests; [Collection("Network")] public class DashboardViewModelTests { + private static DashboardViewModel NewVm() + { + var sys = new SystemInfoService(); + var diskHealth = new DiskHealthService(); + return new DashboardViewModel( + sys, + new TuneUpService(new ShortcutCleanerService(), diskHealth, sys), + new HealthScoreService(sys, diskHealth, new BatteryService()), + new TemperatureService(diskHealth, skipHardwareInit: true)); + } + [Fact] public void Ctor_SetsElevationFlag() { - var vm = new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService())); + var vm = NewVm(); // Just ensures IsElevated is true/false (no throw). _ = vm.IsElevated; } @@ -21,19 +32,18 @@ public void Ctor_SetsElevationFlag() [Fact] public async Task RefreshCommand_CompletesAndPopulatesFields() { - var vm = new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService())); + var vm = NewVm(); await vm.RefreshCommand.ExecuteAsync(null); - Assert.NotNull(vm.Snapshot); Assert.False(string.IsNullOrWhiteSpace(vm.OsLine)); - Assert.False(string.IsNullOrWhiteSpace(vm.CpuLine)); - Assert.False(string.IsNullOrWhiteSpace(vm.MemLine)); Assert.False(string.IsNullOrWhiteSpace(vm.UptimeLine)); + Assert.False(string.IsNullOrWhiteSpace(vm.CpuName)); + Assert.True(vm.RamTotalGB >= 0); } [Fact] public async Task RefreshCommand_ResetsBusyFlag_WhenDone() { - var vm = new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService())); + var vm = NewVm(); await vm.RefreshCommand.ExecuteAsync(null); Assert.False(vm.IsBusy); Assert.False(vm.IsProgressIndeterminate); @@ -42,18 +52,18 @@ public async Task RefreshCommand_ResetsBusyFlag_WhenDone() [Fact] public async Task RefreshCommand_SetsStatusMessage() { - var vm = new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService())); + var vm = NewVm(); await vm.RefreshCommand.ExecuteAsync(null); Assert.False(string.IsNullOrWhiteSpace(vm.StatusMessage)); } [Fact] - public void RequestElevationCommand_WhenAlreadyElevated_DoesNotShutdown() + public void RelaunchAsAdminCommand_Exists() { - // We cannot realistically call RequestElevation in a test because it - // would try to spawn a process and shut the test host down. We only - // verify the command exists and is invokable. - var vm = new DashboardViewModel(new SystemInfoService(), new TuneUpService(new ShortcutCleanerService(), new DiskHealthService(), new SystemInfoService()), new HealthScoreService(new SystemInfoService(), new DiskHealthService(), new BatteryService())); - Assert.NotNull(vm.RequestElevationCommand); + // We cannot realistically invoke RelaunchAsAdmin in a test because it + // would try to spawn an elevated process and shut the test host down. + // We only verify the command exists. + var vm = NewVm(); + Assert.NotNull(vm.RelaunchAsAdminCommand); } } diff --git a/SysManager/SysManager.IntegrationTests/LightTouchViewModelTests.cs b/SysManager/SysManager.IntegrationTests/LightTouchViewModelTests.cs index 7149195..98d9537 100644 --- a/SysManager/SysManager.IntegrationTests/LightTouchViewModelTests.cs +++ b/SysManager/SysManager.IntegrationTests/LightTouchViewModelTests.cs @@ -73,7 +73,7 @@ public void DriversVm_CancelBeforeStart_IsSafe() [Fact] public void WindowsUpdateVm_Ctor_IsSafe() { - var vm = new WindowsUpdateViewModel(new PowerShellRunner()); + var vm = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()); Assert.NotNull(vm.Console); Assert.False(vm.ModuleAvailable); } @@ -81,11 +81,10 @@ public void WindowsUpdateVm_Ctor_IsSafe() [Fact] public void WindowsUpdateVm_AllCommandsExist() { - var vm = new WindowsUpdateViewModel(new PowerShellRunner()); + var vm = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()); Assert.NotNull(vm.CheckModuleCommand); Assert.NotNull(vm.InstallModuleCommand); Assert.NotNull(vm.ListUpdatesCommand); - Assert.NotNull(vm.ListFeatureUpdatesCommand); Assert.NotNull(vm.ShowHistoryCommand); Assert.NotNull(vm.CheckPendingRebootCommand); Assert.NotNull(vm.InstallUpdatesCommand); @@ -93,10 +92,12 @@ public void WindowsUpdateVm_AllCommandsExist() } [Fact] - public void WindowsUpdateVm_ModuleStatusDefault_IsChecking() + public void WindowsUpdateVm_ModuleStatusDefault_IsSet() { - var vm = new WindowsUpdateViewModel(new PowerShellRunner()); - Assert.Contains("Checking", vm.ModuleStatus, StringComparison.OrdinalIgnoreCase); + var vm = new WindowsUpdateViewModel(new PowerShellRunner(), new WindowsUpdateService()); + // Since the WUA COM migration, updates use the COM API directly and + // PSWindowsUpdate backs only the History view; the default status reflects that. + Assert.False(string.IsNullOrWhiteSpace(vm.ModuleStatus)); } // ---------- App updates ---------- diff --git a/SysManager/SysManager.IntegrationTests/LogsViewModelExtendedTests.cs b/SysManager/SysManager.IntegrationTests/LogsViewModelExtendedTests.cs index 3573d95..b35d557 100644 --- a/SysManager/SysManager.IntegrationTests/LogsViewModelExtendedTests.cs +++ b/SysManager/SysManager.IntegrationTests/LogsViewModelExtendedTests.cs @@ -66,7 +66,7 @@ public void Defaults_LogFolderIsSet() public void Defaults_SearchTextIsEmpty() { var vm = new LogsViewModel(new EventLogService()); - Assert.Equal("", vm.SearchText); + Assert.Equal("", vm.FilterText); } [Fact] @@ -115,11 +115,11 @@ public void Filter_SearchText_IsCaseInsensitive() { var vm = new LogsViewModel(new EventLogService()); var e = Make(EventSeverity.Error, "Disk controller timeout"); - vm.SearchText = "DISK"; + vm.FilterText = "DISK"; Assert.True(InvokeFilter(vm, e)); - vm.SearchText = "disk"; + vm.FilterText = "disk"; Assert.True(InvokeFilter(vm, e)); - vm.SearchText = "Disk"; + vm.FilterText = "Disk"; Assert.True(InvokeFilter(vm, e)); } @@ -128,7 +128,7 @@ public void Filter_SearchByProvider_Works() { var vm = new LogsViewModel(new EventLogService()); var e = Make(EventSeverity.Error, "m", "Microsoft-Windows-Kernel-Power", 41); - vm.SearchText = "Kernel"; + vm.FilterText = "Kernel"; Assert.True(InvokeFilter(vm, e)); } @@ -137,7 +137,7 @@ public void Filter_SearchByEventIdNumeric_Works() { var vm = new LogsViewModel(new EventLogService()); var e = Make(EventSeverity.Error, "m", "x", 41); - vm.SearchText = "41"; + vm.FilterText = "41"; Assert.True(InvokeFilter(vm, e)); } @@ -146,7 +146,7 @@ public void Filter_SearchMissingText_ReturnsFalse() { var vm = new LogsViewModel(new EventLogService()); var e = Make(EventSeverity.Error, "simple message"); - vm.SearchText = "nowhere-to-be-found"; + vm.FilterText = "nowhere-to-be-found"; Assert.False(InvokeFilter(vm, e)); } @@ -244,7 +244,7 @@ public void ChangingSearchText_RefreshesView_NoThrow() var vm = new LogsViewModel(new EventLogService()); var ex = Record.Exception(() => { - for (int i = 0; i < 20; i++) vm.SearchText = $"query{i}"; + for (int i = 0; i < 20; i++) vm.FilterText = $"query{i}"; }); Assert.Null(ex); } diff --git a/SysManager/SysManager.IntegrationTests/QaResilienceTests.cs b/SysManager/SysManager.IntegrationTests/QaResilienceTests.cs index a062414..1978a78 100644 --- a/SysManager/SysManager.IntegrationTests/QaResilienceTests.cs +++ b/SysManager/SysManager.IntegrationTests/QaResilienceTests.cs @@ -126,7 +126,7 @@ public void HealthAnalyzer_StaticThresholds_AreConstants() public void LogsViewModel_SearchSpecialChars_DoesNotCrashFilter(string q) { var vm = new LogsViewModel(new EventLogService()); - vm.SearchText = q; + vm.FilterText = q; var m = typeof(LogsViewModel).GetMethod("EntryFilter", BindingFlags.NonPublic | BindingFlags.Instance)!; var e = new FriendlyEventEntry { Severity = EventSeverity.Error, Message = "ok", EventId = 1 }; diff --git a/SysManager/SysManager.IntegrationTests/WindowsUpdateAutoCheckTests.cs b/SysManager/SysManager.IntegrationTests/WindowsUpdateAutoCheckTests.cs index 3d23dad..39327f7 100644 --- a/SysManager/SysManager.IntegrationTests/WindowsUpdateAutoCheckTests.cs +++ b/SysManager/SysManager.IntegrationTests/WindowsUpdateAutoCheckTests.cs @@ -9,7 +9,7 @@ namespace SysManager.IntegrationTests; public class WindowsUpdateAutoCheckTests { - private static WindowsUpdateViewModel Build() => new(new PowerShellRunner()); + private static WindowsUpdateViewModel Build() => new(new PowerShellRunner(), new WindowsUpdateService()); [Fact] public void ModuleStatus_HasInitialMessage() diff --git a/SysManager/SysManager.IntegrationTests/WindowsUpdateViewModelTests.cs b/SysManager/SysManager.IntegrationTests/WindowsUpdateViewModelTests.cs index 6c37c69..ed0aaa0 100644 --- a/SysManager/SysManager.IntegrationTests/WindowsUpdateViewModelTests.cs +++ b/SysManager/SysManager.IntegrationTests/WindowsUpdateViewModelTests.cs @@ -10,7 +10,7 @@ namespace SysManager.IntegrationTests; public class WindowsUpdateViewModelTests { - private static WindowsUpdateViewModel NewVm() => new(new PowerShellRunner()); + private static WindowsUpdateViewModel NewVm() => new(new PowerShellRunner(), new WindowsUpdateService()); // ---------- construction ---------- @@ -117,7 +117,7 @@ public async Task InstallUpdates_WhenNotElevated_SetsStatusMessage() public void RunnerLineReceived_AppendsToConsole() { var runner = new PowerShellRunner(); - var vm = new WindowsUpdateViewModel(runner); + var vm = new WindowsUpdateViewModel(runner, new WindowsUpdateService()); var ev = typeof(PowerShellRunner) .GetField(nameof(PowerShellRunner.LineReceived), @@ -134,7 +134,7 @@ public void RunnerLineReceived_AppendsToConsole() public void RunnerProgressChanged_UpdatesProgress() { var runner = new PowerShellRunner(); - var vm = new WindowsUpdateViewModel(runner); + var vm = new WindowsUpdateViewModel(runner, new WindowsUpdateService()); var ev = typeof(PowerShellRunner) .GetField(nameof(PowerShellRunner.ProgressChanged),