Phase 2-3: UI layout, theme switching, CRUD tools, process execution
- Phase 2: MainWindow 3-section layout (sidebar/content/log bar), Dark/Light theme with ThemeHelper, MainViewModel with ObservableProperty/RelayCommand, tool card filtering by search + category - Phase 3: ToolEditWindow for add/edit tools, ProcessExecutionService (Process.Start + error handling), double-click + right-click context menu (run/edit), path browse dialog - Bugfix: ContextMenu commands now use PlacementTarget.Tag binding (ContextMenu in separate visual tree) - Bugfix: StaticResource converters moved to XAML before DataTemplate to fix XamlParseException on tool card render - Bugfix: Pure filenames (no path separators) treated as PATH commands, not marked invalid - Bugfix: RefreshData preserves SelectedCategory; Load() catches all exceptions; Save() wrapped in try-catch; auto-scroll log to newest entry - Tests: xUnit project with 55 tests covering models, services, converters, and view models
This commit is contained in:
118
PersonalToolBox.Tests/Models/ModelSerializationTests.cs
Normal file
118
PersonalToolBox.Tests/Models/ModelSerializationTests.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System.Text.Json;
|
||||
using PersonalToolBox.Models;
|
||||
|
||||
namespace PersonalToolBox.Tests.Models;
|
||||
|
||||
public class ModelSerializationTests
|
||||
{
|
||||
private static readonly JsonSerializerOptions Options = new()
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void AppConfig_Serialize_ProducesValidJson()
|
||||
{
|
||||
var config = new AppConfig
|
||||
{
|
||||
Theme = "Dark",
|
||||
AutoStart = true,
|
||||
Categories =
|
||||
[
|
||||
new() { Id = "1", Name = "开发工具" },
|
||||
new() { Id = "2", Name = "常用脚本" }
|
||||
],
|
||||
Tools =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Id = "tool-1",
|
||||
Name = "Postman",
|
||||
IconCode = "f0c2",
|
||||
ExecutablePath = @"D:\tools\postman.exe",
|
||||
Arguments = "",
|
||||
CategoryId = "1",
|
||||
HotKey = "Ctrl+Alt+P"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(config, Options);
|
||||
var deserialized = JsonSerializer.Deserialize<AppConfig>(json, Options);
|
||||
|
||||
Assert.NotNull(deserialized);
|
||||
Assert.Equal("Dark", deserialized.Theme);
|
||||
Assert.True(deserialized.AutoStart);
|
||||
Assert.Equal(2, deserialized.Categories.Count);
|
||||
Assert.Single(deserialized.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToolItem_IsValid_NotIncludedInJson()
|
||||
{
|
||||
var tool = new ToolItem
|
||||
{
|
||||
Name = "TestTool",
|
||||
ExecutablePath = @"C:\nonexistent.exe",
|
||||
IsValid = false
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(tool, Options);
|
||||
|
||||
Assert.DoesNotContain("IsValid", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToolItem_DefaultValues_AreCorrect()
|
||||
{
|
||||
var tool = new ToolItem();
|
||||
|
||||
Assert.NotEmpty(tool.Id);
|
||||
Assert.Empty(tool.Name);
|
||||
Assert.True(tool.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Category_DefaultId_IsNotEmpty()
|
||||
{
|
||||
var cat = new Category();
|
||||
Assert.NotEmpty(cat.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AppConfig_DefaultValues_AreCorrect()
|
||||
{
|
||||
var config = new AppConfig();
|
||||
|
||||
Assert.Equal("Dark", config.Theme);
|
||||
Assert.False(config.AutoStart);
|
||||
Assert.NotNull(config.Categories);
|
||||
Assert.NotNull(config.Tools);
|
||||
Assert.Empty(config.Categories);
|
||||
Assert.Empty(config.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_EmptyJson_ProducesValidConfig()
|
||||
{
|
||||
var json = "{}";
|
||||
var config = JsonSerializer.Deserialize<AppConfig>(json, Options);
|
||||
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal("Dark", config.Theme);
|
||||
Assert.False(config.AutoStart);
|
||||
Assert.Empty(config.Categories);
|
||||
Assert.Empty(config.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Deserialize_WithUnknownProperty_IgnoresIt()
|
||||
{
|
||||
var json = """{"unknownField": 123, "Theme": "Light"}""";
|
||||
var config = JsonSerializer.Deserialize<AppConfig>(json, Options);
|
||||
|
||||
Assert.NotNull(config);
|
||||
Assert.Equal("Light", config.Theme);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user