File: OperationTests.MinimalApis.cs
Web Access
Project: src\src\OpenApi\test\Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests\Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests.csproj (Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests)
// 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.Json.Nodes;
using Microsoft.OpenApi.Models;
 
namespace Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests;
 
[UsesVerify]
public partial class OperationTests
{
    [Fact]
    public async Task SupportsXmlCommentsOnOperationsFromMinimalApis()
    {
        var source = """
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Http;
 
var builder = WebApplication.CreateBuilder();
 
builder.Services.AddOpenApi();
 
var app = builder.Build();
 
app.MapGet("/1", RouteHandlerExtensionMethods.Get);
app.MapGet("/2", RouteHandlerExtensionMethods.Get2);
app.MapGet("/3", RouteHandlerExtensionMethods.Get3);
app.MapGet("/4", RouteHandlerExtensionMethods.Get4);
app.MapGet("/5", RouteHandlerExtensionMethods.Get5);
app.MapPost("/6", RouteHandlerExtensionMethods.Post6);
app.MapPut("/7", RouteHandlerExtensionMethods.Put7);
 
app.Run();
 
public static class RouteHandlerExtensionMethods
{
    /// <summary>
    /// A summary of the action.
    /// </summary>
    /// <description>
    /// A description of the action.
    /// </description>
    public static string Get()
    {
        return "Hello, World!";
    }
 
    /// <param name="name">The name of the person.</param>
    /// <response code="200">Returns the greeting.</response>
    public static string Get2(string name)
    {
        return $"Hello, {name}!";
    }
 
    /// <param name="name" example="Testy McTester">The name of the person.</param>
    public static string Get3(string name)
    {
        return $"Hello, {name}!";
    }
 
    /// <response code="404">Indicates that the value was not found.</response>
    public static NotFound<string> Get4()
    {
        return TypedResults.NotFound("Not found!");
    }
 
    /// <response code="200">Indicates that the value is even.</response>
    /// <response code="201">Indicates that the value is less than 50.</response>
    /// <response code="404">Indicates that the value was not found.</response>
    public static Results<NotFound<string>, Ok<string?>, Created> Get5()
    {
        var randomNumber = Random.Shared.Next();
        if (randomNumber % 2 == 0)
        {
            return TypedResults.Ok("is even");
        }
        else if (randomNumber < 50)
        {
            return TypedResults.Created("is less than 50");
        }
        return TypedResults.NotFound("Not found!");
    }
 
    /// <summary>
    /// Creates a new user.
    /// </summary>
    /// <remarks>
    /// Sample request:
    ///     POST /6
    ///     {
    ///         "username": "johndoe",
    ///         "email": "john@example.com"
    ///     }
    /// </remarks>
    /// <param name="user" example='{"username": "johndoe", "email": "john@example.com"}'>The user information.</param>
    /// <response code="201">Successfully created the user.</response>
    /// <response code="400">If the user data is invalid.</response>
    public static IResult Post6(User user)
    {
        return TypedResults.Created($"/users/{user.Username}", user);
    }
 
    /// <summary>
    /// Updates an existing record.
    /// </summary>
    /// <param name="id" deprecated="true">Legacy ID parameter - use uuid instead.</param>
    /// <param name="uuid">Unique identifier for the record.</param>
    /// <response code="204">Update successful.</response>
    /// <response code="404" deprecated="true">Legacy response - will be removed.</response>
    public static IResult Put7(int? id, string uuid)
    {
        return TypedResults.NoContent();
    }
}
 
public class User
{
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
}
""";
        var generator = new XmlCommentGenerator();
        await SnapshotTestHelper.Verify(source, generator, out var compilation);
        await SnapshotTestHelper.VerifyOpenApi(compilation, document =>
        {
            var path = document.Paths["/1"].Operations[OperationType.Get];
            Assert.Equal("A summary of the action.", path.Summary);
            Assert.Equal("A description of the action.", path.Description);
 
            var path2 = document.Paths["/2"].Operations[OperationType.Get];
            Assert.Equal("The name of the person.", path2.Parameters[0].Description);
            Assert.Equal("Returns the greeting.", path2.Responses["200"].Description);
 
            var path3 = document.Paths["/3"].Operations[OperationType.Get];
            Assert.Equal("The name of the person.", path3.Parameters[0].Description);
            var example = Assert.IsAssignableFrom<JsonNode>(path3.Parameters[0].Example);
            Assert.Equal("\"Testy McTester\"", example.ToJsonString());
 
            var path4 = document.Paths["/4"].Operations[OperationType.Get];
            var response = path4.Responses["404"];
            Assert.Equal("Indicates that the value was not found.", response.Description);
 
            var path5 = document.Paths["/5"].Operations[OperationType.Get];
            Assert.Equal("Indicates that the value was not found.", path5.Responses["404"].Description);
            Assert.Equal("Indicates that the value is even.", path5.Responses["200"].Description);
            Assert.Equal("Indicates that the value is less than 50.", path5.Responses["201"].Description);
 
            var path6 = document.Paths["/6"].Operations[OperationType.Post];
            Assert.Equal("Creates a new user.", path6.Summary);
            Assert.Contains("Sample request:", path6.Description);
            var userParam = path6.RequestBody.Content["application/json"];
            var userExample = Assert.IsAssignableFrom<JsonNode>(userParam.Example);
            Assert.Equal("johndoe", userExample["username"].GetValue<string>());
 
            var path7 = document.Paths["/7"].Operations[OperationType.Put];
            var idParam = path7.Parameters.First(p => p.Name == "id");
            Assert.True(idParam.Deprecated);
            Assert.Equal("Legacy ID parameter - use uuid instead.", idParam.Description);
        });
    }
}