diff --git a/test/Falco.OpenApi.Tests.App/Falco.OpenApi.Tests.App.fsproj b/test/Falco.OpenApi.Tests.App/Falco.OpenApi.Tests.App.fsproj
new file mode 100644
index 0000000..dd6ad9d
--- /dev/null
+++ b/test/Falco.OpenApi.Tests.App/Falco.OpenApi.Tests.App.fsproj
@@ -0,0 +1,18 @@
+
+
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Falco.OpenApi.Tests.App/Program.fs b/test/Falco.OpenApi.Tests.App/Program.fs
new file mode 100644
index 0000000..0c7e9e6
--- /dev/null
+++ b/test/Falco.OpenApi.Tests.App/Program.fs
@@ -0,0 +1,62 @@
+module Falco.OpenApi.Tests.App
+
+open Falco
+open Falco.OpenApi
+open Falco.Routing
+open Microsoft.AspNetCore.Builder
+open Microsoft.Extensions.DependencyInjection
+open Microsoft.Extensions.Hosting
+
+type Greeting =
+ { Message : string }
+
+let endpoints =
+ [
+ get "/" (Response.ofPlainText "Hello World!")
+ |> OpenApi.name "HelloWorld"
+ |> OpenApi.summary "A hello world greeter"
+ |> OpenApi.description "This is a simple endpoint that will return a greeting message."
+
+ mapGet "/hello/{name?}"
+ (fun route ->
+ let name = route?name.AsStringNonEmpty("world")
+ let age = route?age.AsIntOption()
+
+ let message =
+ match age with
+ | Some a -> $"Hello {name}, you are {a} years old!"
+ | _ -> $"Hello {name}!"
+
+ { Message = message })
+ Response.ofJson
+ |> OpenApi.name "Greeting"
+ |> OpenApi.summary "A friendly greeter"
+ |> OpenApi.description "This endpoint will provide a customized greeting based on the name and age (optional) provided."
+ |> OpenApi.route [
+ { Type = typeof; Name = "Name"; Required = false } ]
+ |> OpenApi.query [
+ { Type = typeof; Name = "Age"; Required = false } ]
+ |> OpenApi.acceptsType typeof
+ |> OpenApi.returnType typeof
+ ]
+
+let bldr = WebApplication.CreateBuilder()
+
+bldr.Services
+ .AddFalcoOpenApi()
+ .AddSwaggerGen()
+ |> ignore
+
+let wapp = bldr.Build()
+
+wapp.UseHttpsRedirection()
+ .UseSwagger()
+ .UseSwaggerUI()
+|> ignore
+
+wapp.UseFalco(endpoints)
+|> ignore
+
+wapp.Run()
+
+type Program() = class end
diff --git a/test/Falco.OpenApi.Tests.App/appsettings.json b/test/Falco.OpenApi.Tests.App/appsettings.json
new file mode 100644
index 0000000..e797029
--- /dev/null
+++ b/test/Falco.OpenApi.Tests.App/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Urls": "https://localhost:5001",
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information"
+ }
+ }
+}
diff --git a/test/Falco.OpenApi.Tests/Falco.OpenApi.Tests.fsproj b/test/Falco.OpenApi.Tests/Falco.OpenApi.Tests.fsproj
index 92041af..98980ed 100644
--- a/test/Falco.OpenApi.Tests/Falco.OpenApi.Tests.fsproj
+++ b/test/Falco.OpenApi.Tests/Falco.OpenApi.Tests.fsproj
@@ -1,4 +1,4 @@
-
+
net8.0
false
@@ -6,6 +6,8 @@
+
+
@@ -26,6 +28,7 @@
-
+
+
diff --git a/test/Falco.OpenApi.Tests/OpenApiTests.fs b/test/Falco.OpenApi.Tests/OpenApiTests.fs
new file mode 100644
index 0000000..4e8c77a
--- /dev/null
+++ b/test/Falco.OpenApi.Tests/OpenApiTests.fs
@@ -0,0 +1,123 @@
+module Falco.OpenApi.Tests.OpenApi
+
+open Xunit
+
+[]
+let ``Can GET /hello``() =
+ let factory = FalcoOpenApiTestServer.createFactory ()
+ let client = factory.CreateClient()
+ let response = client.GetAsync("/").Result
+ let content = response.Content.ReadAsStringAsync().Result
+ Assert.Equal("Hello World!", content)
+
+[]
+let ``Can GET /hello/{name?}`` () =
+ let factory = FalcoOpenApiTestServer.createFactory ()
+ let client = factory.CreateClient()
+ let response = client.GetAsync("/hello").Result
+ let content = response.Content.ReadAsStringAsync().Result
+ Assert.Equal("""{"Message":"Hello world!"}""", content)
+
+ let response = client.GetAsync("/hello/John").Result
+ let content = response.Content.ReadAsStringAsync().Result
+ Assert.Equal("""{"Message":"Hello John!"}""", content)
+
+ let response = client.GetAsync("/hello/John?age=42").Result
+ let content = response.Content.ReadAsStringAsync().Result
+ Assert.Equal("""{"Message":"Hello John, you are 42 years old!"}""", content)
+
+let private expectedOpenApiDoc = """{
+ "openapi": "3.0.1",
+ "info": {
+ "title": "testhost",
+ "version": "1.0"
+ },
+ "paths": {
+ "/hello/{name}": {
+ "get": {
+ "tags": [
+ "Greeting"
+ ],
+ "summary": "A friendly greeter",
+ "description": "This endpoint will provide a customized greeting based on the name and age (optional) provided.",
+ "operationId": "Greeting",
+ "parameters": [
+ {
+ "name": "Name",
+ "in": "path",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "Age",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "text/plain": {
+ "schema": {
+ "type": "string"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Greeting"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/": {
+ "get": {
+ "tags": [
+ "HelloWorld"
+ ],
+ "summary": "A hello world greeter",
+ "description": "This is a simple endpoint that will return a greeting message.",
+ "operationId": "HelloWorld",
+ "responses": {
+ "200": {
+ "description": "OK"
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Greeting": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "nullable": true
+ }
+ },
+ "additionalProperties": false
+ }
+ }
+ }
+}"""
+
+[]
+let ``Can GET /swagger/v1/swagger.json`` () =
+ let factory = FalcoOpenApiTestServer.createFactory ()
+ let client = factory.CreateClient()
+ let response = client.GetAsync("/swagger/v1/swagger.json").Result
+ let content = response.Content.ReadAsStringAsync().Result
+ Assert.Equal(expectedOpenApiDoc, content)
diff --git a/test/Falco.OpenApi.Tests/TestHelpers.fs b/test/Falco.OpenApi.Tests/TestHelpers.fs
new file mode 100644
index 0000000..8951476
--- /dev/null
+++ b/test/Falco.OpenApi.Tests/TestHelpers.fs
@@ -0,0 +1,9 @@
+namespace Falco.OpenApi.Tests
+
+open Microsoft.AspNetCore.Mvc.Testing
+open Microsoft.AspNetCore.TestHost
+open Falco.OpenApi.Tests.App
+
+module FalcoOpenApiTestServer =
+ let createFactory() =
+ new WebApplicationFactory()