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

361 lines
9.0 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.Mvc.Analyzers.Infrastructure;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Analyzers
{
public class ApiActionsDoNotRequireExplicitModelValidationCheckFacts : AnalyzerTestBase
{
protected override DiagnosticAnalyzer DiagnosticAnalyzer { get; }
= new ApiActionsDoNotRequireExplicitModelValidationCheckAnalyzer();
protected override CodeFixProvider CodeFixProvider { get; }
= new ApiActionsDoNotRequireExplicitModelValidationCheckCodeFixProvider();
[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_WhenActionDoesNotHaveModelStateCheck()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : Controller
{
public IActionResult GetPetId()
{
return Ok(new object());
}
}";
var project = CreateProject(test);
// Act
var result = await GetDiagnosticAsync(project);
// Assert
Assert.Empty(result);
}
[Fact]
public async Task NoDiagnosticsAreReturned_WhenAActionsUseExpressionBodies()
{
// Arrange
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : Controller
{
public IActionResult GetPetId() => ModelState.IsVald ? OK() : BadResult();
}";
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 : ControllerBase
{
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 Task DiagnosticsAndCodeFixes_WhenActionHasModelStateIsValidCheck()
{
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (!ModelState.IsValid)
{
return BadRequest();
}
return Ok();
}
}";
// Act & Assert
return VerifyAsync(test);
}
[Fact]
public Task DiagnosticsAndCodeFixes_WhenActionHasModelStateIsValidCheck_UsingComparisonToFalse()
{
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (ModelState.IsValid == false)
{
return BadRequest();
}
return Ok();
}
}";
// Act & Assert
return VerifyAsync(test);
}
[Fact]
public Task DiagnosticsAndCodeFixes_WhenActionHasModelStateIsValidCheck_WithoutBraces()
{
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (!ModelState.IsValid)
return BadRequest();
return Ok();
}
}";
return VerifyAsync(test);
}
private async Task VerifyAsync(string test)
{
// Arrange
var expectedDiagnostic = new DiagnosticResult
{
Id = "MVC1001",
Message = "Actions on types annotated with ApiControllerAttribute do not require explicit ModelState validity check.",
Severity = DiagnosticSeverity.Warning,
Locations = new[] { new DiagnosticResultLocation("Test.cs", 9, 9) }
};
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
return Ok();
}
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
Assert.DiagnosticsEqual(new[] { expectedDiagnostic }, actualDiagnostics);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Fact]
public async Task DiagnosticsAndCodeFixes_WhenModelStateIsInElseIf()
{
// Arrange
var expectedDiagnostic = new DiagnosticResult
{
Id = "MVC1001",
Message = "Actions on types annotated with ApiControllerAttribute do not require explicit ModelState validity check.",
Severity = DiagnosticSeverity.Warning,
Locations = new[] { new DiagnosticResultLocation("Test.cs", 13, 9) }
};
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (User == null)
{
return Unauthorized();
}
else if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
}";
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (User == null)
{
return Unauthorized();
}
return Ok();
}
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
Assert.DiagnosticsEqual(new[] { expectedDiagnostic }, actualDiagnostics);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
[Fact]
public async Task DiagnosticsAndCodeFixes_WhenModelStateIsInNestedBlock()
{
// Arrange
var expectedDiagnostic = new DiagnosticResult
{
Id = "MVC1001",
Message = "Actions on types annotated with ApiControllerAttribute do not require explicit ModelState validity check.",
Severity = DiagnosticSeverity.Warning,
Locations = new[] { new DiagnosticResultLocation("Test.cs", 15, 13) }
};
var test =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (User == null)
{
return Unauthorized();
}
else
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Debug.Assert(ModelState.Count == 0);
}
return Ok();
}
}";
var expectedFix =
@"
using Microsoft.AspNetCore.Mvc;
[ApiController]
public class PetController : ControllerBase
{
public IActionResult GetPetId()
{
if (User == null)
{
return Unauthorized();
}
else
{
Debug.Assert(ModelState.Count == 0);
}
return Ok();
}
}";
var project = CreateProject(test);
// Act & Assert
var actualDiagnostics = await GetDiagnosticAsync(project);
Assert.DiagnosticsEqual(new[] { expectedDiagnostic }, actualDiagnostics);
var actualFix = await ApplyCodeFixAsync(project, actualDiagnostics);
Assert.Equal(expectedFix, actualFix, ignoreLineEndingDifferences: true);
}
}
}