|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.AspNetCore.Routing;
public partial class OpenApiDocumentServiceTests : OpenApiDocumentServiceTestBase
{
[Fact]
public async Task GetOpenApiPaths_ReturnsPaths()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/api/todos", () => { });
builder.MapGet("/api/users", () => { });
// Assert
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos", path.Key);
Assert.Collection(path.Value.Operations.OrderBy(o => o.Key),
operation =>
{
Assert.Equal(HttpMethod.Get, operation.Key);
});
},
path =>
{
Assert.Equal("/api/users", path.Key);
Assert.Collection(path.Value.Operations.OrderBy(o => o.Key),
operation =>
{
Assert.Equal(HttpMethod.Get, operation.Key);
});
});
});
}
[Fact]
public async Task GetOpenApiPaths_RespectsShouldInclude()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/api/todos", () => { }).WithMetadata(new EndpointGroupNameAttribute("v1"));
builder.MapGet("/api/users", () => { }).WithMetadata(new EndpointGroupNameAttribute("v2"));
// Assert -- The default `ShouldInclude` implementation only includes endpoints that
// match the document name. Since we don't set a document name explicitly, this will
// match against the default document name ("v1") and the document will only contain
// the endpoint with that group name.
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos", path.Key);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_RespectsShouldInclude_CaseInsensitive()
{
// Arrange
var builder = CreateBuilder();
var openApiOptions = new OpenApiOptions { DocumentName = "firstgroup" };
// Act
builder.MapGet("/api/todos", () => { }).WithMetadata(new EndpointGroupNameAttribute("FirstGroup"));
builder.MapGet("/api/users", () => { }).WithMetadata(new EndpointGroupNameAttribute("SecondGroup"));
// Assert -- The default `ShouldInclude` implementation should include endpoints that
// match the document name case-insensitively. The document name is "firstgroup" (lowercase)
// but the endpoint group name is "FirstGroup" (mixed case), and it should still match.
await VerifyOpenApiDocument(builder, openApiOptions, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos", path.Key);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_RespectsSamePaths()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/api/todos", () => { });
builder.MapPost("/api/todos", () => { });
// Assert
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos", path.Key);
Assert.Equal(2, path.Value.Operations.Count);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
Assert.Contains(HttpMethod.Post, path.Value.Operations);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_HandlesRouteParameters()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/api/todos/{id}", () => { });
builder.MapPost("/api/todos/{id}", () => { });
builder.MapMethods("/api/todos/{id}", ["PATCH", "PUT"], () => { });
// Assert
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos/{id}", path.Key);
Assert.Equal(4, path.Value.Operations.Count);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
Assert.Contains(HttpMethod.Put, path.Value.Operations);
Assert.Contains(HttpMethod.Post, path.Value.Operations);
Assert.Contains(HttpMethod.Patch, path.Value.Operations);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_HandlesRouteConstraints()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/api/todos/{id:int}", () => { });
builder.MapPost("/api/todos/{id:int}", () => { });
// Assert
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/api/todos/{id}", path.Key);
Assert.Equal(2, path.Value.Operations.Count);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
Assert.Contains(HttpMethod.Post, path.Value.Operations);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_HandlesRoutesStartingWithTilde()
{
// Arrange
var builder = CreateBuilder();
// Act
builder.MapGet("/~health", () => "Healthy");
builder.MapGet("/~api/todos", () => { });
builder.MapGet("/~api/todos/{id}", () => { });
builder.MapGet("~/health2", () => "Healthy2");
// Assert
await VerifyOpenApiDocument(builder, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/~api/todos", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
},
path =>
{
Assert.Equal("/~api/todos/{id}", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
},
path =>
{
Assert.Equal("/~health", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
},
path =>
{
Assert.Equal("/health2", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_HandlesRoutesStartingWithTilde_MvcAction()
{
// Arrange
var action = CreateActionDescriptor(nameof(ActionWithTildeRoute));
// Assert
await VerifyOpenApiDocument(action, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/~health", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
}
);
});
}
[Fact]
public async Task GetOpenApiPaths_HandlesRoutesStartingWithTildeBeforeSlash_MvcAction()
{
// Arrange
var action = CreateActionDescriptor(nameof(ActionWithTildeBeforeSlashRoute));
// Assert
await VerifyOpenApiDocument(action, document =>
{
Assert.Collection(document.Paths.OrderBy(p => p.Key),
path =>
{
Assert.Equal("/health", path.Key);
Assert.Single(path.Value.Operations);
Assert.Contains(HttpMethod.Get, path.Value.Operations);
}
);
});
}
[Route("/~health")]
private void ActionWithTildeRoute() { }
[Route("~/health")]
private void ActionWithTildeBeforeSlashRoute() { }
}
|