diff --git a/obp-api/src/main/scala/code/api/v5_0_0/Http4s500.scala b/obp-api/src/main/scala/code/api/v5_0_0/Http4s500.scala index 671e4e244..a957601a4 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/Http4s500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/Http4s500.scala @@ -11,8 +11,10 @@ import code.api.util.http4s.ResourceDocMiddleware import code.api.util.http4s.Http4sRequestAttributes.EndpointHelpers import code.api.util.{CustomJsonFormats, NewStyle} import code.api.v4_0_0.JSONFactory400 +import code.api.v5_0_0.JSONFactory500 import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global +import com.openbankproject.commons.model.BankId import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus, ScannedApiVersion} import net.liftweb.json.JsonAST.prettyRender import net.liftweb.json.{Extraction, Formats} @@ -101,10 +103,43 @@ object Http4s500 { } } + resourceDocs += ResourceDoc( + null, + implementedInApiVersion, + nameOf(getBank), + "GET", + "/banks/BANK_ID", + "Get Bank", + """Get the bank specified by BANK_ID + |Returns information about a single bank specified by BANK_ID including: + | + |* Bank code and full name of bank + |* Logo URL + |* Website""", + EmptyBody, + bankJson500, + List( + UnknownError, + BankNotFound + ), + apiTagBank :: apiTagPSD2AIS :: apiTagPsd2 :: Nil, + http4sPartialFunction = Some(getBank) + ) + + val getBank: HttpRoutes[IO] = HttpRoutes.of[IO] { + case req @ GET -> `prefixPath` / "banks" / bankId => + EndpointHelpers.withBank(req) { (bank, cc) => + for { + (attributes, callContext) <- NewStyle.function.getBankAttributesByBank(BankId(bankId), Some(cc)) + } yield JSONFactory500.createBankJSON500(bank, attributes) + } + } + val allRoutes: HttpRoutes[IO] = Kleisli[HttpF, Request[IO], Response[IO]] { req: Request[IO] => root(req) .orElse(getBanks(req)) + .orElse(getBank(req)) } val allRoutesWithMiddleware: HttpRoutes[IO] = @@ -113,4 +148,3 @@ object Http4s500 { val wrappedRoutesV500Services: HttpRoutes[IO] = Implementations5_0_0.allRoutesWithMiddleware } - diff --git a/obp-api/src/test/scala/code/api/v5_0_0/Http4s500RoutesTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/Http4s500RoutesTest.scala index 443966606..1832cdd7a 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/Http4s500RoutesTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/Http4s500RoutesTest.scala @@ -2,6 +2,7 @@ package code.api.v5_0_0 import cats.effect.IO import cats.effect.unsafe.implicits.global +import code.api.util.APIUtil import code.setup.ServerSetupWithTestData import net.liftweb.json.JValue import net.liftweb.json.JsonAST.{JArray, JField, JObject} @@ -70,5 +71,26 @@ class Http4s500RoutesTest extends ServerSetupWithTestData { } } } -} + feature("Http4s500 bank endpoint") { + + scenario("Return single bank JSON", Http4s500RoutesTag) { + val request = Request[IO]( + method = Method.GET, + uri = Uri.unsafeFromString(s"/obp/v5.0.0/banks/${APIUtil.defaultBankId}") + ) + + val (status, json) = runAndParseJson(request) + + status shouldBe Status.Ok + json match { + case JObject(fields) => + val keys = fields.map(_.name) + keys should contain("id") + keys should contain("bank_code") + case _ => + fail("Expected JSON object for get bank endpoint") + } + } + } +} diff --git a/obp-api/src/test/scala/code/api/v5_0_0/V500ContractParityTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/V500ContractParityTest.scala index 16e3fc145..6265f36fd 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/V500ContractParityTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/V500ContractParityTest.scala @@ -2,8 +2,9 @@ package code.api.v5_0_0 import cats.effect.IO import cats.effect.unsafe.implicits.global +import code.api.util.APIUtil import net.liftweb.json.JValue -import net.liftweb.json.JsonAST.{JArray, JField, JObject} +import net.liftweb.json.JsonAST.{JArray, JField, JObject, JString} import net.liftweb.json.JsonParser.parse import org.http4s.{Method, Request, Status, Uri} import org.scalatest.Tag @@ -27,6 +28,17 @@ class V500ContractParityTest extends V500ServerSetup { fields.map(field => field.name -> field.value).toMap } + private def getStringField(json: JValue, key: String): Option[String] = { + json match { + case JObject(fields) => + toFieldMap(fields).get(key) match { + case Some(JString(v)) => Some(v) + case _ => None + } + case _ => None + } + } + feature("V500 Lift vs http4s parity") { scenario("root returns consistent status and key fields", V500ContractParityTag) { @@ -84,6 +96,16 @@ class V500ContractParityTest extends V500ServerSetup { fail("Expected http4s JSON object for banks endpoint") } } + + scenario("bank returns consistent status and bank id", V500ContractParityTag) { + val bankId = APIUtil.defaultBankId + val liftResponse = makeGetRequest((v5_0_0_Request / "banks" / bankId).GET) + val (http4sStatus, http4sJson) = http4sRunAndParseJson(s"/obp/v5.0.0/banks/$bankId") + + liftResponse.code should equal(http4sStatus.code) + + getStringField(liftResponse.body, "id") shouldBe Some(bankId) + getStringField(http4sJson, "id") shouldBe Some(bankId) + } } } -