test/ add tests for http4s-only resource docs and version validation

Add integration tests to verify that the /resource-docs endpoint returns only http4s technology endpoints and rejects requests for non-v7 API versions. This ensures proper filtering and version handling in the http4s routes.
This commit is contained in:
hongwei 2026-01-28 15:23:44 +01:00
parent b29f21232e
commit 54a1552643
2 changed files with 102 additions and 20 deletions

View File

@ -9,7 +9,7 @@ import code.api.util.APIUtil.{EmptyBody, _}
import code.api.util.ApiRole.canGetCardsForBank
import code.api.util.ApiTag._
import code.api.util.ErrorMessages._
import code.api.util.http4s.{Http4sRequestAttributes, ResourceDocMiddleware}
import code.api.util.http4s.{ErrorResponseConverter, Http4sRequestAttributes, ResourceDocMiddleware}
import code.api.util.http4s.Http4sRequestAttributes.{RequestOps, EndpointHelpers}
import code.api.util.{ApiVersionUtils, CallContext, CustomJsonFormats, NewStyle}
import code.api.v1_3_0.JSONFactory1_3_0
@ -26,6 +26,7 @@ import org.http4s.dsl.io._
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.Future
import scala.language.{higherKinds, implicitConversions}
import scala.util.{Failure, Success, Try}
object Http4s700 {
@ -201,25 +202,31 @@ object Http4s700 {
val getResourceDocsObpV700: HttpRoutes[IO] = HttpRoutes.of[IO] {
case req @ GET -> `prefixPath` / "resource-docs" / requestedApiVersionString / "obp" =>
EndpointHelpers.executeAndRespond(req) { _ =>
val queryParams = req.uri.query.multiParams
val tags = queryParams
.get("tags")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).map(ResourceDocTag(_)).toList)
val functions = queryParams
.get("functions")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).toList)
val localeParam = queryParams
.get("locale")
.flatMap(_.headOption)
.orElse(queryParams.get("language").flatMap(_.headOption))
.map(_.trim)
.filter(_.nonEmpty)
for {
requestedApiVersion <- Future(ApiVersionUtils.valueOf(requestedApiVersionString))
resourceDocs = ResourceDocs140.ImplementationsResourceDocs.getResourceDocsList(requestedApiVersion).getOrElse(Nil)
filteredDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, tags, functions)
} yield JSONFactory1_4_0.createResourceDocsJson(filteredDocs, isVersion4OrHigher = true, localeParam, includeTechnology = true)
implicit val cc: CallContext = req.callContext
val queryParams = req.uri.query.multiParams
val tags = queryParams
.get("tags")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).map(ResourceDocTag(_)).toList)
val functions = queryParams
.get("functions")
.map(_.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty).toList)
val localeParam = queryParams
.get("locale")
.flatMap(_.headOption)
.orElse(queryParams.get("language").flatMap(_.headOption))
.map(_.trim)
.filter(_.nonEmpty)
Try(ApiVersionUtils.valueOf(requestedApiVersionString)) match {
case Success(requestedApiVersion) if requestedApiVersion == ApiVersion.v7_0_0 =>
val http4sOnlyDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs.toList, tags, functions)
EndpointHelpers.executeAndRespond(req) { _ =>
Future.successful(JSONFactory1_4_0.createResourceDocsJson(http4sOnlyDocs, isVersion4OrHigher = true, localeParam, includeTechnology = true))
}
case Success(_) =>
ErrorResponseConverter.createErrorResponse(400, s"API Version not supported by this server: $requestedApiVersionString", cc)
case Failure(_) =>
ErrorResponseConverter.createErrorResponse(400, s"Invalid API Version: $requestedApiVersionString", cc)
}
}

View File

@ -267,6 +267,81 @@ class Http4s700RoutesTest extends ServerSetupWithTestData {
}
}
scenario("Return only http4s technology endpoints", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v7.0.0/obp request")
setPropsValues("resource_docs_requires_role" -> "false")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/resource-docs/v7.0.0/obp")
)
When("Running through wrapped routes")
val (status, json) = runAndParseJson(request)
Then("Response is 200 OK and includes no lift endpoints")
status shouldBe Status.Ok
json match {
case JObject(fields) =>
toFieldMap(fields).get("resource_docs") match {
case Some(JArray(resourceDocs)) =>
resourceDocs.exists {
case JObject(rdFields) =>
toFieldMap(rdFields).get("implemented_by") match {
case Some(JObject(implFields)) =>
toFieldMap(implFields).get("technology") match {
case Some(JString(value)) => value == "http4s"
case _ => false
}
case _ => false
}
case _ => false
} shouldBe true
resourceDocs.exists {
case JObject(rdFields) =>
toFieldMap(rdFields).get("implemented_by") match {
case Some(JObject(implFields)) =>
toFieldMap(implFields).get("technology") match {
case Some(JString(value)) => value == "lift"
case _ => false
}
case _ => false
}
case _ => false
} shouldBe false
case _ =>
fail("Expected resource_docs field to be an array")
}
case _ =>
fail("Expected JSON object for resource-docs endpoint")
}
}
scenario("Reject requesting non-v7 API version docs", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v6.0.0/obp request")
setPropsValues("resource_docs_requires_role" -> "false")
val request = Request[IO](
method = Method.GET,
uri = Uri.unsafeFromString("/obp/v7.0.0/resource-docs/v6.0.0/obp")
)
When("Running through wrapped routes")
val (status, json) = runAndParseJson(request)
Then("Response is 400 Bad Request")
status.code shouldBe 400
json match {
case JObject(fields) =>
toFieldMap(fields).get("message") match {
case Some(JString(message)) =>
message should include("API Version not supported")
case _ =>
fail("Expected message field as JSON string for invalid-version response")
}
case _ =>
fail("Expected JSON object for invalid-version response")
}
}
scenario("Reject unauthenticated access when resource docs role is required", Http4s700RoutesTag) {
Given("GET /obp/v7.0.0/resource-docs/v7.0.0/obp request without auth headers and role required")
setPropsValues("resource_docs_requires_role" -> "true")