File: Agents\CopilotAppInstallationDetectorTests.cs
Web Access
Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Cli.Agents.Copilot;
using Aspire.Cli.Tests.Utils;
 
namespace Aspire.Cli.Tests.Agents;
 
public class CopilotAppInstallationDetectorTests(ITestOutputHelper outputHelper)
{
    [Fact]
    public async Task GetInstallationMarker_WhenWindowsAppExecutableExists_ReturnsPath()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var localAppData = workspace.CreateDirectory("local-app-data");
        var appDirectory = Directory.CreateDirectory(
            Path.Combine(localAppData.FullName, "Programs", "GitHub Copilot"));
        await File.WriteAllTextAsync(
            Path.Combine(appDirectory.FullName, "github.exe"),
            string.Empty,
            TestContext.Current.CancellationToken);
        var environment = TestEnvironment.CreateWindows(new Dictionary<string, string?>
        {
            ["LOCALAPPDATA"] = localAppData.FullName,
        });
        var executablePath = Path.Combine(appDirectory.FullName, "github.exe");
 
        Assert.Equal(executablePath, CreateDetector(environment, workspace).GetInstallationMarker());
    }
 
    [Fact]
    public void GetInstallationMarker_WhenUserMacOSAppBundleExists_ReturnsPath()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var appBundlePath = Path.Combine(workspace.WorkspaceRoot.FullName, "Applications", "GitHub Copilot.app");
        Directory.CreateDirectory(appBundlePath);
 
        Assert.Equal(appBundlePath, CreateDetector(TestEnvironment.CreateMacOS(), workspace).GetInstallationMarker());
    }
 
    [Fact]
    public void GetInstallationMarker_WhenRuntimeMarkerIsPresent_ReturnsEnvironmentVariable()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var environment = TestEnvironment.CreateLinux(new Dictionary<string, string?>
        {
            [CopilotAppInstallationDetector.AgentEnvironmentVariable] =
                CopilotAppInstallationDetector.AgentEnvironmentValue,
        });
 
        Assert.Equal(
            CopilotAppInstallationDetector.AgentEnvironmentVariable,
            CreateDetector(environment, workspace).GetInstallationMarker());
    }
 
    [Fact]
    public async Task GetInstallationMarker_WhenLinuxDesktopEntryExists_ReturnsPath()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var applicationsDirectory = workspace.CreateDirectory(
            Path.Combine(".local", "share", "applications"));
        await File.WriteAllTextAsync(
            Path.Combine(applicationsDirectory.FullName, "github-copilot.desktop"),
            """
            [Desktop Entry]
            Name=GitHub Copilot
            Exec=/opt/github-copilot/github
            """,
            TestContext.Current.CancellationToken);
        var desktopEntryPath = Path.Combine(applicationsDirectory.FullName, "github-copilot.desktop");
 
        Assert.Equal(
            desktopEntryPath,
            CreateDetector(TestEnvironment.CreateLinux(), workspace).GetInstallationMarker());
    }
 
    [Fact]
    public void GetLinuxApplicationDirectories_WithoutXdgOverrides_UsesFreedesktopDefaults()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var detector = CreateDetector(TestEnvironment.CreateLinux(), workspace);
        var rootDirectory = Path.DirectorySeparatorChar.ToString();
 
        Assert.Equal(
            [
                Path.Combine(workspace.WorkspaceRoot.FullName, ".local", "share", "applications"),
                Path.Combine(rootDirectory, "usr", "local", "share", "applications"),
                Path.Combine(rootDirectory, "usr", "share", "applications"),
            ],
            detector.GetLinuxApplicationDirectories());
    }
 
    [Fact]
    public void GetLinuxApplicationDirectories_WithXdgOverrides_UsesAbsoluteEntries()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var dataHome = workspace.CreateDirectory("xdg-data-home");
        var firstDataDirectory = workspace.CreateDirectory("xdg-data-first");
        var secondDataDirectory = workspace.CreateDirectory("xdg-data-second");
        var environment = TestEnvironment.CreateLinux(new Dictionary<string, string?>
        {
            ["XDG_DATA_HOME"] = dataHome.FullName,
            ["XDG_DATA_DIRS"] = string.Join(
                Path.PathSeparator,
                firstDataDirectory.FullName,
                "relative-directory",
                secondDataDirectory.FullName),
        });
        var detector = CreateDetector(environment, workspace);
 
        Assert.Equal(
            [
                Path.Combine(dataHome.FullName, "applications"),
                Path.Combine(firstDataDirectory.FullName, "applications"),
                Path.Combine(secondDataDirectory.FullName, "applications"),
            ],
            detector.GetLinuxApplicationDirectories());
    }
 
    [Fact]
    public void GetInstallationMarker_WithoutInstallationOrRuntimeMarker_ReturnsNull()
    {
        using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
        var dataHome = workspace.CreateDirectory("xdg-data-home");
        var dataDirectory = workspace.CreateDirectory("xdg-data-dir");
        var environment = TestEnvironment.CreateLinux(new Dictionary<string, string?>
        {
            ["XDG_DATA_HOME"] = dataHome.FullName,
            ["XDG_DATA_DIRS"] = dataDirectory.FullName,
        });
        Assert.Null(CreateDetector(environment, workspace).GetInstallationMarker());
    }
 
    private static CopilotAppInstallationDetector CreateDetector(
        IEnvironment environment,
        TemporaryWorkspace workspace)
    {
        return new(
            environment,
            TestExecutionContextHelper.CreateExecutionContext(
                workspace.WorkspaceRoot,
                homeDirectory: workspace.WorkspaceRoot));
    }
}