Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Key services:
human-readable explanations.
- `HealthAnalyzer` — raw SMART / ping data into verdict pills.
- `SystemInfoService` — OS / CPU / RAM / uptime snapshot.
- `TuneUpService` — orchestrates the Quick Tune-Up wizard: temp cleanup,
Recycle Bin, shortcut scan, disk SMART, uptime/RAM checks. Non-destructive.
- `LogService` — Serilog wrapper with rolling file sink.
- `FixedDriveService` — enumerate fixed NTFS/ReFS volumes.
- `DeepCleanupService` — scan-first safe cleanup (vendor caches, gaming
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]

### Added
- **Dashboard — Quick Tune-Up wizard** — one-click button that runs safe
cleanup (temp files), optionally empties Recycle Bin (with confirmation),
scans for broken shortcuts (report only), checks disk SMART health,
flags high uptime (14+ days) and high RAM usage (85%+). Displays a
dismissible summary card with freed space, disk verdicts, and
recommendations. Non-destructive, no admin required. Closes #261.
- **IntGreaterThanZeroConverter** — value converter for conditional
visibility when an integer is greater than zero.
- **IDialogService** — abstraction for user confirmation dialogs, replacing
direct `MessageBox.Show` calls in ViewModels. Enables unit testing of
confirmation-gated code paths (CQ-003).
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ long-running operation, so you always know which tab is working.
### Dashboard
- One-line OS / CPU / RAM / disk summary
- Live uptime counter
- **Quick Tune-Up** — one-click wizard that cleans temp files, optionally
empties the Recycle Bin, scans for broken shortcuts, checks disk SMART
health, flags high uptime (14+ days) and high RAM usage (85%+). Displays
a summary card with freed space, warnings, and links to relevant tabs.
Non-destructive, no admin required.

### Updates (for SysManager itself)
- Auto-check on startup against the GitHub Releases API, plus a manual
Expand Down
84 changes: 83 additions & 1 deletion SysManager/SysManager.Tests/DashboardViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ namespace SysManager.Tests;
/// </summary>
public class DashboardViewModelTests
{
private static DashboardViewModel NewVm() => new(new SystemInfoService());
private static DashboardViewModel NewVm()
{
var sys = new SystemInfoService();
return new DashboardViewModel(sys, new TuneUpService(
new ShortcutCleanerService(), new DiskHealthService(), sys));
}

// ---------- construction & defaults ----------

Expand Down Expand Up @@ -127,4 +132,81 @@ public void Setter_FiresPropertyChanged(string propName, string value)
typeof(DashboardViewModel).GetProperty(propName)!.SetValue(vm, value);
Assert.True(fired);
}

// ---------- Tune-Up properties ----------

[Fact]
public void Constructor_TuneUpProperties_DefaultValues()
{
var vm = NewVm();
Assert.False(vm.IsTuneUpRunning);
Assert.Equal("", vm.TuneUpStep);
Assert.Equal(0, vm.TuneUpProgress);
Assert.Null(vm.TuneUpResult);
Assert.False(vm.HasTuneUpResult);
}

[Theory]
[InlineData("RunTuneUpCommand")]
[InlineData("CancelTuneUpCommand")]
[InlineData("DismissTuneUpResultCommand")]
public void TuneUpCommand_IsExposedAndNotNull(string name)
{
var vm = NewVm();
var prop = vm.GetType().GetProperty(name);
Assert.NotNull(prop);
Assert.NotNull(prop!.GetValue(vm));
}

[Fact]
public void DismissTuneUpResult_ClearsResult()
{
var vm = NewVm();
// Simulate having a result
vm.HasTuneUpResult = true;
vm.TuneUpResult = new Models.TuneUpResult();

vm.DismissTuneUpResultCommand.Execute(null);

Assert.False(vm.HasTuneUpResult);
Assert.Null(vm.TuneUpResult);
}

[Fact]
public void TuneUpStep_Setter_FiresPropertyChanged()
{
var vm = NewVm();
var fired = false;
vm.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(vm.TuneUpStep)) fired = true; };
vm.TuneUpStep = "Cleaning temp…";
Assert.True(fired);
}

[Fact]
public void TuneUpProgress_Setter_FiresPropertyChanged()
{
var vm = NewVm();
var fired = false;
vm.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(vm.TuneUpProgress)) fired = true; };
vm.TuneUpProgress = 50;
Assert.True(fired);
}

[Fact]
public void IsTuneUpRunning_Setter_FiresPropertyChanged()
{
var vm = NewVm();
var fired = false;
vm.PropertyChanged += (_, e) => { if (e.PropertyName == nameof(vm.IsTuneUpRunning)) fired = true; };
vm.IsTuneUpRunning = true;
Assert.True(fired);
}

[Fact]
public void Dispose_DoesNotThrow()
{
var vm = NewVm();
var ex = Record.Exception(() => vm.Dispose());
Assert.Null(ex);
}
}
50 changes: 50 additions & 0 deletions SysManager/SysManager.Tests/IntGreaterThanZeroConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SysManager · IntGreaterThanZeroConverterTests
// Author: laurentiu021 · https://github.com/laurentiu021/SystemManager
// License: MIT

using System.Globalization;
using SysManager.Helpers;

namespace SysManager.Tests;

/// <summary>
/// Tests for <see cref="IntGreaterThanZeroConverter"/>.
/// </summary>
public class IntGreaterThanZeroConverterTests
{
private readonly IntGreaterThanZeroConverter _sut = new();

[Theory]
[InlineData(0, false)]
[InlineData(-1, false)]
[InlineData(-100, false)]
[InlineData(1, true)]
[InlineData(5, true)]
[InlineData(100, true)]
public void Convert_ReturnsExpected(int input, bool expected)
{
var result = _sut.Convert(input, typeof(bool), null!, CultureInfo.InvariantCulture);
Assert.Equal(expected, result);
}

[Fact]
public void Convert_NonInt_ReturnsFalse()
{
var result = _sut.Convert("hello", typeof(bool), null!, CultureInfo.InvariantCulture);
Assert.Equal(false, result);
}

[Fact]
public void Convert_Null_ReturnsFalse()
{
var result = _sut.Convert(null!, typeof(bool), null!, CultureInfo.InvariantCulture);
Assert.Equal(false, result);
}

[Fact]
public void ConvertBack_ThrowsNotSupported()
{
Assert.Throws<NotSupportedException>(() =>
_sut.ConvertBack(true, typeof(int), null!, CultureInfo.InvariantCulture));
}
}
Loading
Loading