diff --git a/docs/knowledgebase/gui-architecture-deferred.md b/docs/knowledgebase/gui-architecture-deferred.md index 3bf3c83a..02d3d143 100644 --- a/docs/knowledgebase/gui-architecture-deferred.md +++ b/docs/knowledgebase/gui-architecture-deferred.md @@ -62,6 +62,7 @@ Plans: `docs/plans/2026-06-03-012`, `021`–`029`, `033`–`057`. Surface refere | Directory picker init/sync → `SettingsService` | Done | plan `075`, PR #123 | | Mod context menu + global flyout → `MenuBuilderService` | Done | plan `072`, PR #130 | +**Headless tests:** `dotnet test src/ModSync.Tests/ModSync.Tests.csproj --filter SettingsService` (plan `077`); `--filter MenuBuilderService` (plan `072`); `--filter DialogServiceTests` / `FileSystemServiceTests` (plan `113`). **Headless tests:** `dotnet test src/ModSync.Tests/ModSync.Tests.csproj --filter SettingsService` (plan `077`); `--filter MenuBuilderService` (plan `072`); `--filter FilterItemModel` (plan `112`). **Headless tests:** `dotnet test src/ModSync.Tests/ModSync.Tests.csproj --filter SettingsService` (plan `077`); `--filter MenuBuilderService` (plan `072`); `--filter FileTreeNode` (plan `111`). **Headless tests:** `dotnet test src/ModSync.Tests/ModSync.Tests.csproj --filter SettingsService` (plan `077`); `--filter MenuBuilderService` (plan `072`); `--filter ArchiveEnumerationService` (plan `110`). diff --git a/docs/plans/2026-06-04-113-test-dialog-filesystem-service-plan.md b/docs/plans/2026-06-04-113-test-dialog-filesystem-service-plan.md new file mode 100644 index 00000000..cd141299 --- /dev/null +++ b/docs/plans/2026-06-04-113-test-dialog-filesystem-service-plan.md @@ -0,0 +1,19 @@ +--- +title: "test: DialogService and FileSystemService basics" +status: shipped +pr: pending +--- + +# test: DialogService and FileSystemService basics + +## Problem + +`DialogService` path-folder helper and `FileSystemService` watcher/dispose lifecycle had no dedicated tests. + +## Solution + +Add `DialogServiceTests` and `FileSystemServiceTests` for constructor validation, empty-path handling, and safe dispose/stop paths. + +## Verification + +`dotnet test src/ModSync.Tests/ModSync.Tests.csproj --filter "FullyQualifiedName~DialogServiceTests|FullyQualifiedName~FileSystemServiceTests" diff --git a/src/ModSync.Tests/DialogServiceTests.cs b/src/ModSync.Tests/DialogServiceTests.cs new file mode 100644 index 00000000..7437ba8d --- /dev/null +++ b/src/ModSync.Tests/DialogServiceTests.cs @@ -0,0 +1,32 @@ +// Copyright 2021-2025 ModSync +// Licensed under the Business Source License 1.1 (BSL 1.1). +// See LICENSE.txt file in the project root for full license information. + +using System; +using System.Threading.Tasks; +using Avalonia.Controls; +using Avalonia.Headless.XUnit; +using ModSync.Services; +using Xunit; + +namespace ModSync.Tests +{ + [Collection(HeadlessTestApp.CollectionName)] + public sealed class DialogServiceTests + { + [Fact(DisplayName = "Constructor rejects null parent window")] + public void Constructor_NullParentWindow_Throws() + { + Assert.Throws(() => new DialogService(null)); + } + + [AvaloniaFact(DisplayName = "GetStorageFolderFromPathAsync returns null for empty path")] + public async Task GetStorageFolderFromPathAsync_EmptyPath_ReturnsNull() + { + var service = new DialogService(new Window()); + + Assert.Null(await service.GetStorageFolderFromPathAsync(string.Empty)); + Assert.Null(await service.GetStorageFolderFromPathAsync(null)); + } + } +} diff --git a/src/ModSync.Tests/FileSystemServiceTests.cs b/src/ModSync.Tests/FileSystemServiceTests.cs new file mode 100644 index 00000000..2cf07d43 --- /dev/null +++ b/src/ModSync.Tests/FileSystemServiceTests.cs @@ -0,0 +1,33 @@ +// Copyright 2021-2025 ModSync +// Licensed under the Business Source License 1.1 (BSL 1.1). +// See LICENSE.txt file in the project root for full license information. + +using ModSync.Services; +using Xunit; + +namespace ModSync.Tests +{ + public sealed class FileSystemServiceTests + { + [Fact(DisplayName = "SetupModDirectoryWatcher does not throw when watcher disabled")] + public void SetupModDirectoryWatcher_Disabled_DoesNotThrow() + { + FileSystemService.SetupModDirectoryWatcher("/tmp", _ => { }); + } + + [Fact(DisplayName = "StopWatcher does not throw on fresh service")] + public void StopWatcher_FreshService_DoesNotThrow() + { + using var service = new FileSystemService(); + service.StopWatcher(); + } + + [Fact(DisplayName = "Dispose can be called multiple times")] + public void Dispose_MultipleCalls_DoesNotThrow() + { + var service = new FileSystemService(); + service.Dispose(); + service.Dispose(); + } + } +}