Skip to content

Expand unit test coverage and stabilize CI#4566

Open
Marc-André Moreau (mamoreau-devolutions) wants to merge 1 commit intomainfrom
mamoreau-devolutions/test-coverage-plan
Open

Expand unit test coverage and stabilize CI#4566
Marc-André Moreau (mamoreau-devolutions) wants to merge 1 commit intomainfrom
mamoreau-devolutions/test-coverage-plan

Conversation

@mamoreau-devolutions
Copy link
Copy Markdown
Contributor

Summary

  • add broad package-engine, telemetry, settings, and app-side unit test coverage
  • extract small test seams/helpers to make parser, operation, updater, and CLI behavior deterministic to test
  • pin Tmds.DBus.Protocol to 0.92.0 to remove the Avalonia NU1903 warning seen in CI

Validation

  • .NET Tests workflow passed on this branch after the coverage and CI follow-up changes

- add broad package-engine, telemetry, settings, and app-side test coverage

- extract targeted test seams and helpers for deterministic parser and operation tests

- pin Tmds.DBus.Protocol to 0.92.0 to remove the Avalonia NU1903 warning

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands automated test coverage across the app, telemetry, settings, and package-engine components, while also extracting deterministic “test seams” from production code to make parsing and orchestration logic reliably unit-testable and CI-stable.

Changes:

  • Added new xUnit test projects plus extensive new unit tests for CLI/settings, telemetry, and package engine behavior (including fixtures and test harness utilities).
  • Refactored selected production code paths to expose deterministic parsing/helpers and test overrides (e.g., updater helpers, manager output parsing, telemetry HTTP seam).
  • Pinned Tmds.DBus.Protocol in the Avalonia project to eliminate a CI warning.

Reviewed changes

Copilot reviewed 89 out of 89 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/UniGetUI/InternalsVisibleTo.cs Exposes UniGetUI internals to the UniGetUI.Tests assembly.
src/UniGetUI/CLIHandler.cs Adds internal overloads that accept args for deterministic CLI testing.
src/UniGetUI/AutoUpdater.Helpers.cs Extracts updater helper logic (URL allow-listing, parsing, registry helpers) for testability.
src/UniGetUI/AutoUpdater.cs Removes inlined helper logic now housed in AutoUpdater.Helpers.
src/UniGetUI.Tests/UniGetUI.Tests.csproj New app-side test project wiring and linked sources for unit tests.
src/UniGetUI.Tests/TestAssembly.cs Disables xUnit parallelization for this test assembly.
src/UniGetUI.Tests/CLIHandlerTests.cs Adds CLI handler coverage (import/export/settings mutations/secure setting toggles).
src/UniGetUI.Tests/AutoUpdaterTests.cs Adds updater helper tests (URL allow-list, installer selection, version/thumbprint/registry parsing).
src/UniGetUI.PackageEngine.Tests/UniGetUI.PackageEngine.Tests.csproj New package-engine test project with fixtures and shared test infrastructure.
src/UniGetUI.PackageEngine.Tests/TestAssembly.cs Disables xUnit parallelization for package-engine tests.
src/UniGetUI.PackageEngine.Tests/HarnessSmokeTests.cs Smoke-tests the test harness builders/helpers.
src/UniGetUI.PackageEngine.Tests/WinGetManagerTests.cs Adds WinGet manager behavior coverage (proxy args, local source classification, failure/recovery flags).
src/UniGetUI.PackageEngine.Tests/ScoopManagerTests.cs Adds Scoop parsing + operation-parameter/result behavior tests using fixtures.
src/UniGetUI.PackageEngine.Tests/PowerShellManagerTests.cs Adds PowerShell manager installed-package parsing tests.
src/UniGetUI.PackageEngine.Tests/PipManagerTests.cs Adds Pip parsing/search ranking + operation helper tests using fixtures.
src/UniGetUI.PackageEngine.Tests/NpmManagerTests.cs Adds npm parsing tests (JSON array + NDJSON fallback, installed/outdated parsing).
src/UniGetUI.PackageEngine.Tests/DotNetManagerTests.cs Adds dotnet tool list parsing tests.
src/UniGetUI.PackageEngine.Tests/ChocolateyManagerTests.cs Adds Chocolatey parsing/source/version/operation helper tests using fixtures.
src/UniGetUI.PackageEngine.Tests/NuGetManifestLoaderTests.cs Adds NuGet manifest URL + fallback behavior tests using a local HTTP server.
src/UniGetUI.PackageEngine.Tests/InstallOptionsFactoryTests.cs Adds InstallOptionsFactory persistence/sanitization/secure-option filtering tests.
src/UniGetUI.PackageEngine.Tests/IgnoredUpdatesDatabaseTests.cs Adds ignored-updates DB behavior tests (wildcards, expiration, pause-time formatting).
src/UniGetUI.PackageEngine.Tests/PackageManagerTests.cs Adds package-manager readiness/path-selection/retry behavior coverage.
src/UniGetUI.PackageEngine.Tests/PackageLoaderPipelineTests.cs Adds package-loader identity, dedupe, lifecycle-event, and filtering tests.
src/UniGetUI.PackageEngine.Tests/UpgradablePackagesLoaderTests.cs Adds upgradable loader behavior tests (skip rules, tag propagation, timer interval config).
src/UniGetUI.PackageEngine.Tests/PackageOperationsTests.cs Adds operation orchestration tests (retry mutations, pre/post ops, badges, install/update/uninstall behaviors).
src/UniGetUI.PackageEngine.Tests/SourceOperationsTests.cs Adds source operation orchestration tests (admin retry behavior, elevator usage, pre-op creation).
src/UniGetUI.PackageEngine.Tests/CargoClientTests.cs Adds Cargo API client tests using local HTTP server and API override seam.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Helpers/TestHttpServer.cs Introduces a lightweight local HTTP listener for deterministic HTTP tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Helpers/PackageEngineFixtureFiles.cs Adds fixture file loader utilities with assertions.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Helpers/LoaderEventRecorder.cs Adds helper to record loader events for assertions.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestPackageManager.cs Adds a configurable fake PackageManager for unit tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestPackageLoader.cs Adds a configurable fake AbstractPackageLoader for identity/lifecycle tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestPackageDetailsHelper.cs Adds a configurable fake details helper for deterministic details tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestPackageOperationHelper.cs Adds a configurable fake operation helper for deterministic parameter/result tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestSourceHelper.cs Adds a configurable fake source helper for source operation tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Fakes/TestUpgradablePackagesLoader.cs Adds a test wrapper exposing internal timer/validation seams for UpgradablePackagesLoader.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Builders/PackageManagerBuilder.cs Adds builder for deterministic test managers and their behaviors.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Builders/PackageBuilder.cs Adds builder for deterministic Package instances.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Builders/PackageDetailsBuilder.cs Adds builder for deterministic PackageDetails instances.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Builders/SourceBuilder.cs Adds builder for deterministic sources used in tests.
src/UniGetUI.PackageEngine.Tests/Infrastructure/Assertions/OperationAssert.cs Adds shared operation assertions (parameters/verdict).
src/UniGetUI.PackageEngine.Tests/Infrastructure/Assertions/PackageAssert.cs Adds shared package assertions (identity/source/version).
src/UniGetUI.PackageEngine.Tests/Fixtures/sample-manager-output.txt Adds baseline fixture content.
src/UniGetUI.PackageEngine.Tests/Fixtures/Scoop/search-output.txt Adds Scoop search output fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Scoop/list-output.txt Adds Scoop list output fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Scoop/status-output.txt Adds Scoop status output fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Scoop/bucket-list-output.txt Adds Scoop bucket list fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Pip/simple-index.json Adds PyPI simple index fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Pip/installed-list.txt Adds pip installed-list fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Pip/outdated-list.txt Adds pip outdated-list fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Npm/search-array-with-warning.txt Adds npm search JSON-array-with-warning fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Npm/search-ndjson.txt Adds npm NDJSON search fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Npm/installed.json Adds npm installed JSON fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Npm/outdated.json Adds npm outdated JSON fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Chocolatey/source-list-output.txt Adds Chocolatey source list fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Chocolatey/search-versions-output.txt Adds Chocolatey version-search fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Chocolatey/list-output.txt Adds Chocolatey list output fixture.
src/UniGetUI.PackageEngine.Tests/Fixtures/Chocolatey/outdated-output.txt Adds Chocolatey outdated output fixture.
src/UniGetUI.PackageEngine.Managers.WinGet/InternalsVisibleTo.cs Exposes WinGet manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Scoop/InternalsVisibleTo.cs Exposes Scoop manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Scoop/Scoop.cs Extracts parsing logic into internal helpers for testability.
src/UniGetUI.PackageEngine.Managers.Scoop/Helpers/ScoopSourceHelper.cs Extracts sources parsing logic into internal helper for testability.
src/UniGetUI.PackageEngine.Managers.PowerShell/InternalsVisibleTo.cs Exposes PowerShell manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.PowerShell/PowerShell.cs Extracts installed package parsing logic for deterministic tests.
src/UniGetUI.PackageEngine.Managers.Pip/InternalsVisibleTo.cs Exposes Pip manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Pip/Pip.cs Extracts search/index parsing + list parsing logic for deterministic tests.
src/UniGetUI.PackageEngine.Managers.Npm/InternalsVisibleTo.cs Exposes npm manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Npm/Npm.cs Extracts npm output parsing logic for deterministic tests.
src/UniGetUI.PackageEngine.Managers.Dotnet/InternalsVisibleTo.cs Exposes Dotnet manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Dotnet/DotNet.cs Extracts dotnet list parsing logic for deterministic tests.
src/UniGetUI.PackageEngine.Managers.Generic.NuGet/InternalsVisibleTo.cs Exposes NuGet internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Chocolatey/InternalsVisibleTo.cs Exposes Chocolatey internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs Extracts Chocolatey parsing logic into internal helpers for testability.
src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateySourceHelper.cs Extracts Chocolatey source parsing logic into internal helper for testability.
src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyDetailsHelper.cs Extracts installable-version parsing for testability.
src/UniGetUI.PackageEngine.Managers.Cargo/InternalsVisibleTo.cs Exposes Cargo manager internals to PackageEngine tests.
src/UniGetUI.PackageEngine.Managers.Cargo/CratesIOClient.cs Adds API URL override seam and exposes Fetch for HTTP tests.
src/UniGetUI.Interface.Telemetry/InternalsVisibleTo.cs Exposes telemetry internals to telemetry tests.
src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs Adds deterministic bitmask computation, test HTTP seam, and reset helper for tests.
src/UniGetUI.Interface.Telemetry.Tests/UniGetUI.Interface.Telemetry.Tests.csproj New telemetry-focused test project.
src/UniGetUI.Interface.Telemetry.Tests/TelemetryHandlerTests.cs Adds telemetry behavior coverage (credentials gating, payload structure, routing, deterministic bitmask).
src/UniGetUI.Core.Settings/SettingsEngine_ImportExport.cs Makes ResetSettings clear in-memory caches in addition to removing files.
src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj Adds secure-settings dependency needed for new tests.
src/UniGetUI.Core.Settings.Tests/TestAssembly.cs Disables xUnit parallelization for settings tests.
src/UniGetUI.Core.Settings.Tests/SettingsImportExportTests.cs Adds settings import/export behavior coverage (sensitive file exclusion, cache reset).
src/UniGetUI.Core.Settings.Tests/SecureSettingsTests.cs Adds secure settings key mapping + persistence/cache behavior tests.
src/UniGetUI.Core.SecureSettings/SecureSettings.cs Adds test override root seam for secure settings storage.
src/UniGetUI.Avalonia/UniGetUI.Avalonia.csproj Pins Tmds.DBus.Protocol to stabilize CI (NU1903 warning removal).
Comments suppressed due to low confidence (3)

src/UniGetUI.Core.Settings/SettingsEngine_ImportExport.cs:93

  • entry.Split("\\")[^1] is Windows-path specific; on non-Windows paths it won’t match and can cause protected files (e.g., TelemetryClientToken) to be deleted unintentionally. Use Path.GetFileName(entry) (as done elsewhere in this file) for a platform-independent check.
        foreach (
            string entry in Directory.EnumerateFiles(CoreData.UniGetUIUserConfigurationDirectory)
        )
        {
            try
            {
                if (new[] { "TelemetryClientToken" }.Contains(entry.Split("\\")[^1]))
                    continue;

src/UniGetUI.Interface.Telemetry/TelemetryHandler.cs:320

  • HttpResponseMessage should be disposed to avoid holding connections/resources longer than necessary (especially since telemetry can send multiple requests over the app’s lifetime). Consider wrapping the result of SendAsync / TestSendAsyncOverride in a using (or otherwise disposing it) after checking the status code.
            HttpResponseMessage response = TestSendAsyncOverride is { } sendAsync
                ? await sendAsync(request)
                : await _httpClient.SendAsync(request);

            if (response.IsSuccessStatusCode)
                Logger.Debug($"[Telemetry] Sent to {fullIndex}");
            else
                Logger.Warn($"[Telemetry] {fullIndex} returned {(int)response.StatusCode}");

src/UniGetUI.PackageEngine.Managers.Cargo/CratesIOClient.cs:101

  • Fetch creates a new HttpClient but never disposes it. This can keep sockets/handlers alive longer than intended; consider either disposing it (using) or reusing a static/shared HttpClient for this client (while still applying CoreTools.GenericHttpClientParameters appropriately).
    internal static T Fetch<T>(Uri url)
    {
        HttpClient client = new(CoreTools.GenericHttpClientParameters);
        client.DefaultRequestHeaders.UserAgent.ParseAdd(CoreData.UserAgentString);

        var manifestStr = client.GetStringAsync(url).GetAwaiter().GetResult();

        var manifest =
            JsonSerializer.Deserialize<T>(manifestStr, options: SerializationHelpers.DefaultOptions)
            ?? throw new NullResponseException($"Null response for request to {url}");

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to +72
if (!string.Equals(uri.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
{
return false;
}

return uri.Host.EndsWith("devolutions.net", StringComparison.OrdinalIgnoreCase)
|| uri.Host.Equals("github.com", StringComparison.OrdinalIgnoreCase)
|| uri.Host.Equals("objects.githubusercontent.com", StringComparison.OrdinalIgnoreCase)
|| uri.Host.Equals(
"release-assets.githubusercontent.com",
StringComparison.OrdinalIgnoreCase
);
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uri.Host.EndsWith("devolutions.net") will also allow unrelated domains like notdevolutions.net (string-suffix match). For a host allow-list, use an exact match (devolutions.net) or a subdomain match (*.devolutions.net) with a dot boundary check (e.g., host.Equals("devolutions.net", ...) || host.EndsWith(".devolutions.net", ...)).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants