File: RouteEmbeddedLanguage\RoutePatternCompletionProviderTests.cs
Web Access
Project: src\src\Framework\AspNetCoreAnalyzers\test\Microsoft.AspNetCore.App.Analyzers.Test.csproj (Microsoft.AspNetCore.App.Analyzers.Test)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Text;
using Microsoft.AspNetCore.Analyzers.RouteEmbeddedLanguage.Infrastructure;
using Microsoft.AspNetCore.InternalTesting;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.AspNetCore.Analyzers.RouteEmbeddedLanguage;
 
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/49126")]
public partial class RoutePatternCompletionProviderTests
{
    private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RoutePatternAnalyzer());
 
    [Fact]
    public async Task Insertion_Literal_NoItems()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""hi$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
");
 
        // Assert
        Assert.False(result.ShouldTriggerCompletion);
        Assert.Null(result.Completions);
    }
 
    [Fact]
    public async Task Insertion_PolicyColon_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
");
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
 
        var description = await result.Service.GetDescriptionAsync(result.Document, result.Completions.ItemsList[0]);
        Assert.Equal("Matches a string that contains only lowercase or uppercase letters A through Z in the English alphabet.", description.Text);
 
        var change = await result.Service.GetChangeAsync(result.Document, result.Completions.ItemsList[0]);
        Assert.Equal("alpha", change.TextChange.NewText);
    }
 
    [Fact]
    public async Task Invoke_PolicyColon_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
    }
 
    [Fact]
    public async Task Invoke_Policy_HasText_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:[|re|]$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
 
        var change = await result.Service.GetChangeAsync(result.Document, result.Completions.ItemsList[0]);
        Assert.Equal("alpha", change.TextChange.NewText);
        Assert.Equal(result.CompletionListSpan, change.TextChange.Span);
    }
 
    [Fact]
    public async Task Invoke_Policy_InText_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:[|alp$$ha|](1)"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
 
        var change = await result.Service.GetChangeAsync(result.Document, result.Completions.ItemsList[0]);
        Assert.Equal("alpha", change.TextChange.NewText);
        Assert.Equal(result.CompletionListSpan, change.TextChange.Span);
    }
 
    [Fact]
    public async Task Invoke_MultiplePolicy_HasText_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:alpha:[|re|]$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
 
        var change = await result.Service.GetChangeAsync(result.Document, result.Completions.ItemsList[0]);
        Assert.Equal("alpha", change.TextChange.NewText);
        Assert.Equal(result.CompletionListSpan, change.TextChange.Span);
    }
 
    [Fact]
    public async Task Insertion_PolicyColon_MultipleOverloads_ReturnPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{hi:$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
    static void M([StringSyntax(""Route"")] string p, int i)
    {
    }
}
");
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_UnsupportedMethod_NoItems()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        M(@""{$$"");
    }
 
    static void M([StringSyntax(""Route"")] string p)
    {
    }
}
");
 
        // Assert
        Assert.Empty(result.Completions.ItemsList);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasDelegate_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", (string id) => "");
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasDelegate_FromRouteAttribute_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", ([FromRoute(Name = ""id1"")]string id) => "");
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id1", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasMethod_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", ExecuteGet);
    }
 
    static string ExecuteGet(string id)
    {
        return """";
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasMethod_HasStarted_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{[|i|]$$"", ExecuteGet);
    }
 
    static string ExecuteGet(string id)
    {
        return """";
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasMethod_NamedParameters_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(handler: ExecuteGet, pattern: @""{$$"", endpoints: null);
    }
 
    static string ExecuteGet(string id)
    {
        return """";
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_HasSpecialTypes_ExcludeSpecialTypes()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Pipelines;
using System.Security.Claims;
using System.Threading;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", ExecuteGet);
    }
 
    static string ExecuteGet(string id, CancellationToken cancellationToken, HttpContext context,
        HttpRequest request, HttpResponse response, ClaimsPrincipal claimsPrincipal,
        IFormFileCollection formFiles, IFormFile formFile, Stream stream, PipeReader pipeReader)
    {
        return """";
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_AsParameters_ReturnObjectParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", ExecuteGet);
    }
 
    static string ExecuteGet([AsParameters] PageData id)
    {
        return """";
    }
 
    class PageData
    {
        public int PageNumber { get; set; }
        [FromRoute]
        public int PageIndex { get; set; }
        [FromServices]
        public object Service { get; set; }
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("PageIndex", i.DisplayText),
            i => Assert.Equal("PageNumber", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_NullDelegate_NoResults()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"", null);
    }
}
");
 
        // Assert
        Assert.Empty(result.Completions.ItemsList);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_EndpointMapGet_Incomplete_NoResults()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
 
class Program
{
    static void Main()
    {
        EndpointRouteBuilderExtensions.MapGet(null, @""{$$"";
    }
}
");
 
        // Assert
        Assert.Empty(result.Completions.ItemsList);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_CustomMapGet_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
 
class Program
{
    static void Main()
    {
        MapCustomThing(null, @""{$$"", (string id) => "");
    }
 
    static void MapCustomThing(IEndpointRouteBuilder endpoints, [StringSyntax(""Route"")] string pattern, Delegate delegate)
    {
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_ParameterInUse_NoResults()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
 
class Program
{
    static void Main()
    {
        MapCustomThing(null, @""{id}/{$$"", (string id) => "");
    }
 
    static void MapCustomThing(IEndpointRouteBuilder endpoints, [StringSyntax(""Route"")] string pattern, Delegate delegate)
    {
    }
}
");
 
        // Assert
        Assert.Empty(result.Completions.ItemsList);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_ParameterInUse_DifferentCase_NoResults()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
 
class Program
{
    static void Main()
    {
        MapCustomThing(null, @""{ID}/{$$"", (string id) => "");
    }
 
    static void MapCustomThing(IEndpointRouteBuilder endpoints, [StringSyntax(""Route"")] string pattern, Delegate delegate)
    {
    }
}
");
 
        // Assert
        Assert.Empty(result.Completions.ItemsList);
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_OtherParameters_ReturnDelegateParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
 
class Program
{
    static void Main()
    {
        MapCustomThing(null, @""{id}/{$$"", (string id, string id2) => "");
    }
 
    static void MapCustomThing(IEndpointRouteBuilder endpoints, [StringSyntax(""Route"")] string pattern, Delegate delegate)
    {
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id2", i.DisplayText));
    }
 
    [Fact]
    public async Task Insertion_ParameterOpenBrace_ControllerAction_HasParameter_ReturnActionParameterItem()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
 
class Program
{
    static void Main()
    {
    }
}
 
public class TestController
{
    [HttpGet(@""{$$"")]
    public object TestAction(int id)
    {
        return null;
    }
}
");
 
        // Assert
        Assert.Collection(
            result.Completions.ItemsList,
            i => Assert.Equal("id", i.DisplayText));
    }
 
    [Fact]
    public async Task Invoke_Comment_PolicyColon_ReturnHttpPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        // lang=Route
        var s = @""{hi:$$"";
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
    }
 
    [Fact]
    public async Task Invoke_Comment_Http_PolicyColon_ReturnHttpPolicies()
    {
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        // lang=Route,Http
        var s = @""{hi:$$"";
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("alpha", result.Completions.ItemsList[0].DisplayText);
    }
 
    [Fact]
    public async Task Invoke_Comment_Component_PolicyColon_ReturnComponentPolicies()
    {
        // Note: This test adds #line pragma comment to simulate that situation in generated Razor source code.
        // See example in https://github.com/dotnet/razor/pull/6997
 
        // Arrange & Act
        var result = await GetCompletionsAndServiceAsync(@"
using System.Diagnostics.CodeAnalysis;
 
class Program
{
    static void Main()
    {
        // lang=Route,Component
        #line 1 ""/user/foo/index.razor""
        var s = @""{hi:$$"";
    }
}
", CompletionTrigger.Invoke);
 
        // Assert
        Assert.NotEmpty(result.Completions.ItemsList);
        Assert.Equal("bool", result.Completions.ItemsList[0].DisplayText);
    }
 
    private Task<CompletionResult> GetCompletionsAndServiceAsync(string source, CompletionTrigger? completionTrigger = null)
    {
        return CompletionTestHelpers.GetCompletionsAndServiceAsync(Runner, source, completionTrigger);
    }
}