Category: swagger

openAPISwaggerUI–part 4–adding tests

This is how I made

https://nuget.org/packages/OpenAPISwaggerUI in order to see the UI for an ASP.NET 9 project.

And hey, if you have any feedback, don’t be shy! Drop by https://github.com/ignatandrei/openAPISwaggerUI/ and let me know.

For testing, I have created a new ASP.NET Core 9 project that can be used to run

app.MapOpenApi();
app.UseOpenAPISwaggerUI();

public partial class Program { }

And I want to see that /swagger endpoint exists . And more, to have pictures with the different UIs.

The WebApplicationFactory is used to create a test server that can be used to test the application. But I need more – to have a real server that can be used to test the application.

I have found this link that show how to start Kestrel server in a test project : https://danieldonbavand.com/2022/06/13/using-playwright-with-the-webapplicationfactory-to-test-a-blazor-application/

And now the code for having the pre-requisites for testing is as easy as pie.

static CustomWebApplicationFactory factory;
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
    
    var exitCode = Microsoft.Playwright.Program.Main(new[] { "install" });
    if (exitCode != 0)
    {
        throw new Exception($"Playwright exited with code {exitCode}");
    }
    factory = new ();
    var url = factory.ServerAddress;
    Console.WriteLine($"Server address: {url}");
}

And we can test the weatherforecast endpoint – because who doesn’t love knowing the weather, right?

[TestMethod]
public async Task TestWeHaveRealWebServer()
{
    
    using var client = factory.CreateDefaultClient();
    var response = await client.GetAsync("/weatherforecast");
    response.EnsureSuccessStatusCode();
    var baseAddress = factory.ServerAddress;
    if(!baseAddress.EndsWith("/"))
    {
        baseAddress += "/";    
    }
    using var playwright = await Playwright.CreateAsync();
    var request = await playwright.APIRequest.NewContextAsync();
        
    var response1 = await request.GetAsync(baseAddress+"weatherforecast");
    Assert.IsTrue(response1.Ok);
}

And to test the endpoints for my library , OpenAPISwaggerUI

[TestMethod]
public async Task TestIntegrationWorks()
{

    var baseAddress = factory.ServerAddress;
    if (!baseAddress.EndsWith("/"))
    {
        baseAddress += "/";
    }
    using var playwright = await Playwright.CreateAsync();
    var request = await playwright.APIRequest.NewContextAsync();

    await using var browser = await playwright.Chromium.LaunchAsync();
    var context = await browser.NewContextAsync(new()
    {
        //RecordVideoDir = curDirVideos
    });
    var page = await browser.NewPageAsync();
    var pageSwagger = await page.GotoAsync(baseAddress + "swagger");
    await page.ScreenshotAsync(new PageScreenshotOptions { Path = "swagger.png" });
    var content= await page.ContentAsync();
    var hrefs = await page.Locator("a").AllAsync();
    
    Assert.IsTrue(hrefs.Count > 0);
    foreach (var li in hrefs)
    {
        var text= await li.TextContentAsync();
        var href = await li.GetAttributeAsync("href");
        ArgumentNullException.ThrowIfNull(href);
        if(href.StartsWith("/"))
        {
            href =  href[1..];
        }
        var pageNew = await browser.NewPageAsync();
        await pageNew.GotoAsync(baseAddress+ href);
        await pageNew.WaitForLoadStateAsync(LoadState.NetworkIdle);
        await pageNew.ScreenshotAsync(new PageScreenshotOptions { Path = $"{text}.png" });


    }
}

openAPISwaggerUI–part 3–add UI for all

This is how I made

https://nuget.org/packages/OpenAPISwaggerUI in order to see the UI for an ASP.NET 9 project.

And hey, if you have any feedback, don’t be shy! Drop by https://github.com/ignatandrei/openAPISwaggerUI/ and let me know.

Now I want the users of my ASP.NET 9 project to have a buffet of Swagger UIs (Swashbuckle, Redoc, Scalar, NSwag, VisualAutomation) and let them pick their favorite flavor.

The master plan? Create an endpoint (let’s call it /swagger) that showcases all these UIs like a proud parent at a talent show.

But wait, there’s more! I want to sprinkle in some custom info – project version, UI links, and other goodies.

Enter the RazorBlade NuGet package, my trusty sidekick for crafting a Razor page.

So I used the RazorBlade nuget package to create a Razor page .

<ItemGroup>
	<PackageReference Include="RazorBlade" Version="0.7.0" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
</ItemGroup>

And voilà, the SwaggerData.cshtml Razor page is born:

@using OpenAPISwaggerUI
@inherits RazorBlade.PlainTextTemplate<SwaggerUIData>

<html>
<body>
    <h1>Swagger UI</h1>
    <h2>
        <a href="@Model.SwaggerEndpoint" target="_blank">SwaggerEndpoint</a>
    </h2>
    <ul>
        <li>
            <a href="@Model.Swashbuckle" target="_blank">Swashbuckle</a>
        </li>
        <li>
            <a href="@Model.NSwag" target="_blank">NSwag</a>
        </li>
        <li>
            <a href="@Model.ReDoc" target="_blank">Redoc</a>
        </li>
        <li>
            <a href="@Model.Scalar" target="_blank">Scalar</a>
        </li>
        <li>
            <a href="@Model.Blockly" target="_blank">VisualAutomation</a>
        </li>
    </ul>
    <small>
        Generated by <a href="https://www.nuget.org/packages/OpenAPISwaggerUI" target="_blank"> @Model.AssemblyName : @Model.MyName</a>
    </small>
</body>
</html>

openAPISwaggerUI–part 2 – add ui for all

This is how I made

https://nuget.org/packages/OpenAPISwaggerUI in order to see the UI for an ASP.NET 9 project.

And hey, if you have any feedback, don’t be shy! Drop by https://github.com/ignatandrei/openAPISwaggerUI/ and let me know.

Step one in this epic quest: add all the mystical references (a.k.a. NuGet packages) to the project file.

	<ItemGroup>
		<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
		<PackageReference Include="NetCore2Blockly" Version="9.2024.1206.813" />
		<PackageReference Include="NSwag.AspNetCore" Version="14.2.0" />
		<PackageReference Include="RSCG_NameGenerator" Version="2024.26.8.2002" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
		<PackageReference Include="Scalar.AspNetCore" Version="1.2.56" />
		<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="7.2.0" />
		<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="7.2.0" />
	</ItemGroup>

Next, I had to figure out how to register these mystical packages to reveal the UI

public static WebApplication UseOpenAPISwaggerUI(this WebApplication app)
{
     
//goto /swagger-Swashbuckle
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/openapi/v1.json", "v1");
    options.RoutePrefix = "swagger-Swashbuckle";
});
//scalar
//goto swagger-scalar/v1
app.MapScalarApiReference(opt =>
{
    opt.EndpointPathPrefix = "/swagger-scalar/{documentName}";
});
//redoc
//goto /api-docs
app.UseReDoc(options =>
{
    options.SpecUrl("/openapi/v1.json");
    options.RoutePrefix = "swagger-redoc";
});

//goto /nswag-swagger
app.UseSwaggerUi(options =>
{
    options.DocumentPath = "/openapi/v1.json";
    options.Path = "/swagger-nswag";
});
//goto /blocklyautomation
app.UseBlocklyUI(app.Environment);
app.UseBlocklyAutomation();
}

After this it was simple to use the extension in program.cs

app.MapOpenApi();
app.UseOpenAPISwaggerUI();

openAPISwaggerUI–part 1- idea

In .NET 9, Microsoft decided to play a little game of “Hide and Seek” with OpenAPI / Swagger JSON generation, leaving the UI part for us to figure out.

So, how do we choose the best UI for our project without turning it into a guessing game?

Well, I thought, why not create a project that lets you try all the options at once? It’s like a buffet, but for UIs!

You can grab it from https://nuget.org/packages/OpenAPISwaggerUI or install it with `dotnet add package OpenAPISwaggerUI`.

The UI I have found are from

Swashbuckle

NSwag

Redoc

Scalar

Visual Automation ( disclosure  : a project of mine )

And hey, if you have any feedback, don’t be shy! Drop by https://github.com/ignatandrei/openAPISwaggerUI/ and let me know.

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.