|
// 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;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.DotNet.Openapi.Tools;
using Microsoft.Extensions.Tools.Internal;
using Xunit.Abstractions;
namespace Microsoft.DotNet.OpenApi.Tests;
public class OpenApiTestBase : IDisposable
{
protected readonly TemporaryDirectory _tempDir;
protected readonly TextWriter _output = new StringWriter();
protected readonly TextWriter _error = new StringWriter();
protected readonly ITestOutputHelper _outputHelper;
protected const string TestTFM = "net10.0";
protected const string Content = @"{""x-generator"": ""NSwag""}"{""x-generator"": ""NSwag""}";
protected const string ActualUrl = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/api-with-examples.yaml";
protected const string BrokenUrl = "https://www.microsoft.com/en-us/dingos.json";
protected const string FakeOpenApiUrl = "https://contoso.com/openapi.json";
protected const string NoDispositionUrl = "https://contoso.com/nodisposition.yaml";
protected const string NoExtensionUrl = "https://contoso.com/noextension";
protected const string NoSegmentUrl = "https://contoso.com";
protected const string DifferentUrl = "https://contoso.com/different.json";
protected const string PackageUrl = "https://go.microsoft.com/fwlink/?linkid=2099561";
protected const string DifferentUrlContent = @"
{
""x-generator"": ""NSwag""
}"{
""x-generator"": ""NSwag""
}";
protected const string PackageUrlContent = @"
{
""Version"" : ""1.0"",
""Packages"" : {
""Microsoft.Azure.SignalR"": ""1.1.0-preview1-10442"",
""Grpc.AspNetCore.Server"": ""0.1.22-pre2"",
""Grpc.Net.ClientFactory"": ""0.1.22-pre2"",
""Google.Protobuf"": ""3.8.0"",
""Grpc.Tools"": ""1.22.0"",
""NSwag.ApiDescription.Client"": ""13.0.3"",
""Microsoft.Extensions.ApiDescription.Client"": ""0.3.0-preview7.19365.7"",
""Newtonsoft.Json"": ""12.0.2""
}
}"{
""Version"" : ""1.0"",
""Packages"" : {
""Microsoft.Azure.SignalR"": ""1.1.0-preview1-10442"",
""Grpc.AspNetCore.Server"": ""0.1.22-pre2"",
""Grpc.Net.ClientFactory"": ""0.1.22-pre2"",
""Google.Protobuf"": ""3.8.0"",
""Grpc.Tools"": ""1.22.0"",
""NSwag.ApiDescription.Client"": ""13.0.3"",
""Microsoft.Extensions.ApiDescription.Client"": ""0.3.0-preview7.19365.7"",
""Newtonsoft.Json"": ""12.0.2""
}
}";
public OpenApiTestBase(ITestOutputHelper output)
{
_tempDir = new TemporaryDirectory();
_outputHelper = output;
}
public TemporaryNSwagProject CreateBasicProject(bool withOpenApi)
{
var nswagJsonFile = "openapi.json";
var project = _tempDir
.WithCSharpProject("testproj", sdk: "Microsoft.NET.Sdk.Web")
.WithTargetFrameworks(TestTFM);
var tmp = project.Dir();
if (withOpenApi)
{
tmp = tmp.WithContentFile(nswagJsonFile);
}
tmp.WithContentFile("Startup.cs")
.Create();
return new TemporaryNSwagProject(project, nswagJsonFile);
}
internal Application GetApplication(bool realHttp = false)
{
IHttpClientWrapper wrapper;
if (realHttp)
{
wrapper = new HttpClientWrapper(new HttpClient());
}
else
{
wrapper = new TestHttpClientWrapper(DownloadMock());
}
return new Application(
_tempDir.Root, wrapper, _output, _error);
}
private static IDictionary<string, Tuple<string, ContentDispositionHeaderValue>> DownloadMock()
{
var noExtension = new ContentDispositionHeaderValue("attachment");
noExtension.Parameters.Add(new NameValueHeaderValue("filename", "filename"));
var extension = new ContentDispositionHeaderValue("attachment");
extension.Parameters.Add(new NameValueHeaderValue("filename", "filename.json"));
var justAttachments = new ContentDispositionHeaderValue("attachment");
return new Dictionary<string, Tuple<string, ContentDispositionHeaderValue>> {
{ FakeOpenApiUrl, Tuple.Create(Content, extension)},
{ DifferentUrl, Tuple.Create<string, ContentDispositionHeaderValue>(DifferentUrlContent, null) },
{ PackageUrl, Tuple.Create<string, ContentDispositionHeaderValue>(PackageUrlContent, null) },
{ NoDispositionUrl, Tuple.Create<string, ContentDispositionHeaderValue>(Content, null) },
{ NoExtensionUrl, Tuple.Create(Content, noExtension) },
{ NoSegmentUrl, Tuple.Create(Content, justAttachments) },
{ BrokenUrl, null }
};
}
protected void AssertNoErrors(int appExitCode)
{
Assert.True(string.IsNullOrEmpty(_error.ToString()), $"Threw error: {_error}");
Assert.Equal(0, appExitCode);
}
public void Dispose()
{
_outputHelper.WriteLine(_output.ToString());
_tempDir.Dispose();
}
}
public sealed class TestHttpClientWrapper : IHttpClientWrapper
{
private readonly IDictionary<string, Tuple<string, ContentDispositionHeaderValue>> _results;
public TestHttpClientWrapper(IDictionary<string, Tuple<string, ContentDispositionHeaderValue>> results)
{
_results = results;
}
public void Dispose()
{
}
public Task<IHttpResponseMessageWrapper> GetResponseAsync(string url)
{
var result = _results[url];
MemoryStream stream = null;
if (result != null)
{
var byteArray = Encoding.ASCII.GetBytes(result.Item1);
stream = new MemoryStream(byteArray);
}
return Task.FromResult<IHttpResponseMessageWrapper>(new TestHttpResponseMessageWrapper(stream, result?.Item2));
}
}
public sealed class TestHttpResponseMessageWrapper : IHttpResponseMessageWrapper
{
public Task<Stream> Stream { get; }
public HttpStatusCode StatusCode { get; } = HttpStatusCode.OK;
public bool IsSuccessCode()
{
return StatusCode switch
{
HttpStatusCode.OK or HttpStatusCode.Created or HttpStatusCode.NoContent or HttpStatusCode.Accepted => true,
_ => false,
};
}
private readonly ContentDispositionHeaderValue _contentDisposition;
public TestHttpResponseMessageWrapper(
MemoryStream stream,
ContentDispositionHeaderValue header)
{
Stream = Task.FromResult<Stream>(stream);
if (header is null && stream is null)
{
StatusCode = HttpStatusCode.NotFound;
}
_contentDisposition = header;
}
public ContentDispositionHeaderValue ContentDisposition()
{
return _contentDisposition;
}
public void Dispose()
{
}
}
public class TemporaryNSwagProject
{
public TemporaryNSwagProject(TemporaryCSharpProject project, string jsonFile)
{
Project = project;
NSwagJsonFile = jsonFile;
}
public TemporaryCSharpProject Project { get; set; }
public string NSwagJsonFile { get; set; }
}
|