using Moq; using PersonalToolBox.Models; using PersonalToolBox.Services; using PersonalToolBox.ViewModels; namespace PersonalToolBox.Tests.ViewModels; public class ToolEditViewModelTests { private readonly Mock _dataServiceMock = new(); private readonly Mock _logServiceMock = new(); private readonly AppConfig _config; public ToolEditViewModelTests() { _config = new AppConfig { Categories = [ new() { Id = "1", Name = "开发工具" } ] }; _dataServiceMock.Setup(d => d.Config).Returns(_config); } [Fact] public void Constructor_AddMode_SetsTitle() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object); Assert.Equal("添加工具", vm.WindowTitle); Assert.Empty(vm.Name); Assert.Empty(vm.ExecutablePath); } [Fact] public void Constructor_EditMode_SetsTitleAndFields() { var tool = new ToolItem { Name = "MyTool", ExecutablePath = @"C:\test.exe", Arguments = "/arg", HotKey = "Ctrl+T", CategoryId = "1" }; var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object, tool); Assert.Equal("编辑工具", vm.WindowTitle); Assert.Equal("MyTool", vm.Name); Assert.Equal(@"C:\test.exe", vm.ExecutablePath); Assert.Equal("/arg", vm.Arguments); Assert.Equal("Ctrl+T", vm.HotKey); } [Fact] public void Save_EmptyName_LogsWarning() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object) { ExecutablePath = @"C:\test.exe" }; vm.SaveCommand.Execute(null); _logServiceMock.Verify(x => x.Warning(It.Is(s => s.Contains("名称不能为空"))), Times.Once); } [Fact] public void Save_EmptyPath_LogsWarning() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object) { Name = "Test" }; vm.SaveCommand.Execute(null); _logServiceMock.Verify(x => x.Warning(It.Is(s => s.Contains("路径不能为空"))), Times.Once); } [Fact] public void Save_AddMode_AddsToolAndCloses() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object) { Name = "NewTool", ExecutablePath = @"C:\test.exe" }; bool? closeResult = null; vm.CloseAction = (r) => closeResult = r; vm.SaveCommand.Execute(null); Assert.True(vm.Saved); Assert.True(closeResult); Assert.Single(_config.Tools); Assert.Equal("NewTool", _config.Tools[0].Name); _dataServiceMock.Verify(x => x.Save(), Times.Once); } [Fact] public void Save_EditMode_UpdatesToolAndCloses() { var tool = new ToolItem { Name = "OldName", ExecutablePath = @"C:\old.exe" }; var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object, tool) { Name = "NewName", ExecutablePath = @"C:\new.exe" }; bool? closeResult = null; vm.CloseAction = (r) => closeResult = r; vm.SaveCommand.Execute(null); Assert.True(vm.Saved); Assert.True(closeResult); Assert.Equal("NewName", tool.Name); Assert.Equal(@"C:\new.exe", tool.ExecutablePath); _dataServiceMock.Verify(x => x.Save(), Times.Once); } [Fact] public void Cancel_ClosesWithoutSaving() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object); bool? closeResult = null; vm.CloseAction = (r) => closeResult = r; vm.CancelCommand.Execute(null); Assert.False(vm.Saved); Assert.False(closeResult); _dataServiceMock.Verify(x => x.Save(), Times.Never); } [Fact] public void Constructor_LoadsCategories() { var vm = new ToolEditViewModel(_dataServiceMock.Object, _logServiceMock.Object); Assert.Single(vm.Categories); Assert.Equal("开发工具", vm.Categories[0].Name); } }