aspnetcore/test/Microsoft.AspNetCore.Mvc.An.../ApiActionsAreAttributeRoute...

304 lines
8.3 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Analyzer.Testing;
using Microsoft.AspNetCore.Mvc.Analyzers.Infrastructure;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Analyzers
{
public class ApiActionsAreAttributeRoutedFacts : AnalyzerTestBase
{
private static DiagnosticDescriptor DiagnosticDescriptor = DiagnosticDescriptors.MVC7000_ApiActionsMustBeAttributeRouted;
protected override DiagnosticAnalyzer DiagnosticAnalyzer { get; }
= new ApiActionsAreAttributeRoutedAnalyzer();
protected override CodeFixProvider CodeFixProvider { get; }
= new ApiActionsAreAttributeRoutedFixProvider();
[Fact]
public async Task NoDiagnosticsAreReturned_FoEmptyScenarios()
{
// Arrange
var test = @"";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task NoDiagnosticsAreReturned_WhenTypeIsNotApiController()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
public IActionResult Index() => View();
}";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task NoDiagnosticsAreReturned_WhenApiControllerActionHasAttribute()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : Controller
{
[HttpGet]
public int GetPetId() => 0;
}";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task NoDiagnosticsAreReturned_ForConstructors()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : Controller
{
public PetController(){ }
}";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task NoDiagnosticsAreReturned_ForNonActions()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : Controller
{
private int GetPetIdPrivate() => 0;
protected int GetPetIdProtected() => 0;
public static IActionResult FindPetByStatus(int status) => null;
[NonAction]
public object Reset(int state) => null;
}";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task DiagnosticsAndCodeFixes_WhenApiControllerActionDoesNotHaveAttribute()
{
// Arrange
var expectedLocation = new DiagnosticLocation("Test.cs", 8, 16);
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController : Controller
{
public int GetPetId() => 0;
}";
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController : Controller
{
[HttpGet]
public int GetPetId() => 0;
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
AssertDiagnostic(expectedLocation, actualDiagnostics);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Fact]
public async Task CodeFixes_ApplyFullyQualifiedNames()
{
// Arrange
var test =
@"
[Microsoft.AspNetCore.Mvc.ApiController]
[Microsoft.AspNetCore.Mvc.Route]
public class PetController
{
public object GetPet() => null;
}";
var expectedFix =
@"
[Microsoft.AspNetCore.Mvc.ApiController]
[Microsoft.AspNetCore.Mvc.Route]
public class PetController
{
[Microsoft.AspNetCore.Mvc.HttpGet]
public object GetPet() => null;
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Theory]
[InlineData("id")]
[InlineData("petId")]
public async Task CodeFixes_WithIdParameter(string idParameter)
{
// Arrange
var test =
$@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{{
public IActionResult Post(string notid, int {idParameter}) => null;
}}";
var expectedFix =
$@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{{
[HttpPost(""{{{idParameter}}}"")]
public IActionResult Post(string notid, int {idParameter}) => null;
}}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Fact]
public async Task CodeFixes_WithRouteParameter()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{
public IActionResult DeletePetByStatus([FromRoute] Status status, [FromRoute] Category category) => null;
}";
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{
[HttpDelete(""{status}/{category}"")]
public IActionResult DeletePetByStatus([FromRoute] Status status, [FromRoute] Category category) => null;
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Fact]
public async Task CodeFixes_WhenAttributeCannotBeInferred()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{
public IActionResult ModifyPet() => null;
}";
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route]
public class PetController
{
[HttpPut]
public IActionResult ModifyPet() => null;
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
// There isn't a good way to test all fixes simultaneously. We'll pick the last one to verify when we
// expect to have 4 fixes.
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics, codeFixIndex: 3);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
private void AssertDiagnostic(DiagnosticLocation expectedLocation, Diagnostic[] actualDiagnostics)
{
// Assert
Assert.Collection(
actualDiagnostics,
diagnostic =>
{
Assert.Equal(DiagnosticDescriptor.Id, diagnostic.Id);
Assert.Same(DiagnosticDescriptor, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(expectedLocation, diagnostic.Location);
});
}
}
}