From 0643b2492fd6bd796cbdffd87afbf1f0ce67067d Mon Sep 17 00:00:00 2001 From: petekirby-ee Date: Tue, 17 Jan 2023 23:22:07 +0000 Subject: [PATCH] API-6156 Upgrades including Java 11 (#108) * API-6156 Copyright year * API-6156 Scalafmt config * API-6156 Scalafmt changes * API-6156 Scalafix config * API-6156 Scalafix changes * API-6156 Scalastyle changes --- .gitignore | 2 + .scalafix.conf | 25 ++++ .scalafmt.conf | 19 +++ .../AcceptanceTestSpec.scala | 2 +- .../ApiSubscriptionFieldsHappySpec.scala | 2 +- .../ApiSubscriptionFieldsUnhappySpec.scala | 2 +- .../ExternalServices.scala | 2 +- ...ubscriptionFieldDefinitionsHappySpec.scala | 2 +- ...scriptionFieldDefinitionsUnhappySpec.scala | 2 +- .../controller/Helper.scala | 16 +++ .../config/ApplicationConfig.scala | 4 +- .../connector/JsonFormatters.scala | 19 +-- ...PushPullNotificationServiceConnector.scala | 52 +++++---- .../ApiFieldDefinitionsController.scala | 31 ++--- .../controller/Binders.scala | 59 +++++----- .../controller/CommonController.scala | 20 ++-- .../controller/Requests.scala | 6 +- .../SubscriptionFieldsController.scala | 41 +++---- .../model/AccessRequirements.scala | 32 +++--- .../model/JsonFormatters.scala | 82 +++++++------ .../apisubscriptionfields/model/Model.scala | 29 ++--- .../model/Responses.scala | 17 +-- .../apisubscriptionfields/model/Shared.scala | 1 - .../apisubscriptionfields/model/Types.scala | 2 +- .../FieldDefinitionRepository.scala | 63 +++++----- .../SubscriptionFieldsRepository.scala | 108 ++++++++++-------- .../service/ApiFieldDefinitionsService.scala | 9 +- .../service/PushPullNotificationService.scala | 34 +++--- .../service/SubscriptionFieldsService.scala | 68 +++++------ .../utils/ApplicationLogger.scala | 2 +- build.sbt | 11 ++ project/plugins.sbt | 4 +- scalastyle-config.xml | 7 +- .../apisubscriptionfields/AsyncHmrcSpec.scala | 10 +- .../FieldDefinitionTestData.scala | 60 +++++----- .../SubscriptionFieldsTestData.scala | 49 ++++---- .../hmrc/apisubscriptionfields/TestData.scala | 12 +- ...PullNotificationServiceConnectorSpec.scala | 100 ++++++++-------- ...FieldDefinitionsControllerDeleteSpec.scala | 20 ++-- ...ApiFieldDefinitionsControllerGetSpec.scala | 30 +++-- ...piFieldDefinitionsControllerPostSpec.scala | 24 ++-- ...ApiFieldDefinitionsControllerPutSpec.scala | 24 ++-- .../SubscriptionFieldsControllerGetSpec.scala | 25 ++-- .../SubscriptionFieldsControllerPutSpec.scala | 31 +++-- .../model/AccessRequirementsSpec.scala | 4 +- .../model/JsonFormatterSpec.scala | 25 ++-- .../model/ModelSpec.scala | 11 +- .../model/ValidationRuleTestData.scala | 6 +- .../ApiFieldDefinitionsRepositorySpec.scala | 24 ++-- .../repository/MongoFormattersSpec.scala | 6 +- .../SubscriptionFieldsRepositorySpec.scala | 55 +++++---- .../ApiFieldDefinitionsServiceSpec.scala | 23 ++-- .../PushPullNotificationServiceSpec.scala | 53 +++++---- .../SubscriptionFieldsServiceSpec.scala | 51 +++++---- 54 files changed, 759 insertions(+), 659 deletions(-) create mode 100644 .scalafix.conf create mode 100644 .scalafmt.conf diff --git a/.gitignore b/.gitignore index df30c7c..bf75a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .* !.gitignore +!.scalafmt.conf +!.scalafix.conf .cache /.classpath diff --git a/.scalafix.conf b/.scalafix.conf new file mode 100644 index 0000000..c923ecf --- /dev/null +++ b/.scalafix.conf @@ -0,0 +1,25 @@ +rules = [ + OrganizeImports +] + +OrganizeImports { + blankLines = Manual + coalesceToWildcardImportThreshold = 5 + expandRelative = true + groupExplicitlyImportedImplicitsSeparately = false + groupedImports = Merge + groups = [ + "re:(javax?|scala)\\." + "---" + "*" + "---" + "play" + "uk.gov.hmrc." + "---" + "uk.gov.hmrc.apisubscriptionfields." + ] + importSelectorsOrder = Ascii + importsOrder = Ascii + preset = DEFAULT + removeUnused = true +} diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..7a1aff6 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,19 @@ +version="3.5.3" +runner.dialect = "scala212" + +maxColumn = 180 + +assumeStandardLibraryStripMargin = true +align.stripMargin = true +align.preset = most +align.multiline = true +indent.extendSite = 4 +indent.defnSite = 4 +align.arrowEnumeratorGenerator = true +align.closeParenSite = true +align.openParenCallSite = false +align.openParenDefnSite = false +align.openParenCtrlSite = false +danglingParentheses.defnSite = true +danglingParentheses.callSite = true +danglingParentheses.exclude = [] \ No newline at end of file diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/AcceptanceTestSpec.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/AcceptanceTestSpec.scala index d19691b..88ab055 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/AcceptanceTestSpec.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/AcceptanceTestSpec.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsHappySpec.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsHappySpec.scala index 7205c3f..ce601dd 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsHappySpec.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsHappySpec.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsUnhappySpec.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsUnhappySpec.scala index 0b4f957..6cc713c 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsUnhappySpec.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/ApiSubscriptionFieldsUnhappySpec.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/ExternalServices.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/ExternalServices.scala index 68501f0..70f5850 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/ExternalServices.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/ExternalServices.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsHappySpec.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsHappySpec.scala index d169685..d5e24e1 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsHappySpec.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsHappySpec.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsUnhappySpec.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsUnhappySpec.scala index 42eb50b..66aa264 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsUnhappySpec.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldDefinitionsUnhappySpec.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020 HM Revenue & Customs + * Copyright 2023 HM Revenue & Customs * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/acceptance/uk/gov/hmrc/apisubscriptionfields/controller/Helper.scala b/acceptance/uk/gov/hmrc/apisubscriptionfields/controller/Helper.scala index b98d33a..ea9c163 100644 --- a/acceptance/uk/gov/hmrc/apisubscriptionfields/controller/Helper.scala +++ b/acceptance/uk/gov/hmrc/apisubscriptionfields/controller/Helper.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2023 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package uk.gov.hmrc.apisubscriptionfields.controller import uk.gov.hmrc.apisubscriptionfields.model.{Types, FieldDefinition} diff --git a/app/uk/gov/hmrc/apisubscriptionfields/config/ApplicationConfig.scala b/app/uk/gov/hmrc/apisubscriptionfields/config/ApplicationConfig.scala index 995cb6d..3d06f56 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/config/ApplicationConfig.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/config/ApplicationConfig.scala @@ -17,6 +17,7 @@ package uk.gov.hmrc.apisubscriptionfields.config import com.google.inject.{ImplementedBy, Inject, Singleton} + import play.api.Configuration @ImplementedBy(classOf[ApplicationConfigImpl]) @@ -25,10 +26,9 @@ trait ApplicationConfig { } @Singleton -class ApplicationConfigImpl @Inject()(config: Configuration) extends ApplicationConfig { +class ApplicationConfigImpl @Inject() (config: Configuration) extends ApplicationConfig { private val HOCON = config.underlying // Moving away from complex layers configurations val pushPullNotificationServiceURL = HOCON.getString("microservice.services.push-pull-notification.uri") } - diff --git a/app/uk/gov/hmrc/apisubscriptionfields/connector/JsonFormatters.scala b/app/uk/gov/hmrc/apisubscriptionfields/connector/JsonFormatters.scala index e0094c4..f62011c 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/connector/JsonFormatters.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/connector/JsonFormatters.scala @@ -17,19 +17,20 @@ package uk.gov.hmrc.apisubscriptionfields.connector import play.api.libs.json._ -import uk.gov.hmrc.apisubscriptionfields.model.{ClientId, BoxId, SubscriptionFieldsId} + +import uk.gov.hmrc.apisubscriptionfields.model.{BoxId, ClientId, SubscriptionFieldsId} trait JsonFormatters { - implicit val clientIdJF = Json.valueFormat[ClientId] - implicit val boxIdJF = Json.valueFormat[BoxId] + implicit val clientIdJF = Json.valueFormat[ClientId] + implicit val boxIdJF = Json.valueFormat[BoxId] implicit val subscriptionFieldsIdJF = Json.valueFormat[SubscriptionFieldsId] - implicit val createBoxRequestJF = Json.format[CreateBoxRequest] - implicit val createBoxResponseJF = Json.format[CreateBoxResponse] - implicit val subscriberRequestJF = Json.format[SubscriberRequest] - implicit val updateSubscriberRequestJF = Json.format[UpdateSubscriberRequest] - implicit val updateSubscriberResponseJF = Json.format[UpdateSubscriberResponse] - implicit val updateCallBackUrlRequestJF = Json.format[UpdateCallBackUrlRequest] + implicit val createBoxRequestJF = Json.format[CreateBoxRequest] + implicit val createBoxResponseJF = Json.format[CreateBoxResponse] + implicit val subscriberRequestJF = Json.format[SubscriberRequest] + implicit val updateSubscriberRequestJF = Json.format[UpdateSubscriberRequest] + implicit val updateSubscriberResponseJF = Json.format[UpdateSubscriberResponse] + implicit val updateCallBackUrlRequestJF = Json.format[UpdateCallBackUrlRequest] implicit val updateCallBackUrlResponseJF = Json.format[UpdateCallBackUrlResponse] } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnector.scala b/app/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnector.scala index acdc72e..956a951 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnector.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnector.scala @@ -17,19 +17,20 @@ package uk.gov.hmrc.apisubscriptionfields.connector import javax.inject.{Inject, Singleton} -import uk.gov.hmrc.apisubscriptionfields.config.ApplicationConfig -import uk.gov.hmrc.apisubscriptionfields.model.Types.FieldValue -import uk.gov.hmrc.apisubscriptionfields.model._ -import uk.gov.hmrc.http.HeaderCarrier -import uk.gov.hmrc.http.HttpClient -import uk.gov.hmrc.http.HttpReads.Implicits._ import scala.concurrent.{ExecutionContext, Future} import scala.util.control.NonFatal + +import uk.gov.hmrc.http.HttpReads.Implicits._ +import uk.gov.hmrc.http.{HeaderCarrier, HttpClient} import uk.gov.hmrc.play.http.metrics.common._ +import uk.gov.hmrc.apisubscriptionfields.config.ApplicationConfig +import uk.gov.hmrc.apisubscriptionfields.model.Types.FieldValue +import uk.gov.hmrc.apisubscriptionfields.model._ + @Singleton -class PushPullNotificationServiceConnector @Inject()(http: HttpClient, appConfig: ApplicationConfig, val apiMetrics: ApiMetrics) - (implicit ec: ExecutionContext) extends RecordMetrics { +class PushPullNotificationServiceConnector @Inject() (http: HttpClient, appConfig: ApplicationConfig, val apiMetrics: ApiMetrics)(implicit ec: ExecutionContext) + extends RecordMetrics { import uk.gov.hmrc.apisubscriptionfields.connector.JsonFormatters._ val api: API = API("api-subscription-fields") @@ -39,32 +40,35 @@ class PushPullNotificationServiceConnector @Inject()(http: HttpClient, appConfig def ensureBoxIsCreated(boxName: String, clientId: ClientId)(implicit hc: HeaderCarrier): Future[BoxId] = { val payload = CreateBoxRequest(boxName, clientId) - http.PUT[CreateBoxRequest, CreateBoxResponse](s"$externalServiceUri/box", payload) - .map(_.boxId) - .recover { - case NonFatal(e) => throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") - } + http + .PUT[CreateBoxRequest, CreateBoxResponse](s"$externalServiceUri/box", payload) + .map(_.boxId) + .recover { case NonFatal(e) => + throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") + } } def subscribe(boxId: BoxId, callbackUrl: String)(implicit hc: HeaderCarrier): Future[Unit] = { val payload = UpdateSubscriberRequest(SubscriberRequest(callbackUrl, "API_PUSH_SUBSCRIBER")) - http.PUT[UpdateSubscriberRequest, UpdateSubscriberResponse](s"$externalServiceUri/box/${boxId.value.toString}/subscriber", payload) - .map(_ => ()) - .recover { - case NonFatal(e) => throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") - } + http + .PUT[UpdateSubscriberRequest, UpdateSubscriberResponse](s"$externalServiceUri/box/${boxId.value.toString}/subscriber", payload) + .map(_ => ()) + .recover { case NonFatal(e) => + throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") + } } - def updateCallBackUrl(clientId: ClientId, boxId: BoxId, callbackUrl: FieldValue) - (implicit hc: HeaderCarrier): Future[PPNSCallBackUrlValidationResponse] = { + def updateCallBackUrl(clientId: ClientId, boxId: BoxId, callbackUrl: FieldValue)(implicit hc: HeaderCarrier): Future[PPNSCallBackUrlValidationResponse] = { val payload = UpdateCallBackUrlRequest(clientId, callbackUrl) - http.PUT[UpdateCallBackUrlRequest, UpdateCallBackUrlResponse](s"$externalServiceUri/box/${boxId.value.toString}/callback", payload) + http + .PUT[UpdateCallBackUrlRequest, UpdateCallBackUrlResponse](s"$externalServiceUri/box/${boxId.value.toString}/callback", payload) .map(response => if (response.successful) PPNSCallBackUrlSuccessResponse else response.errorMessage.fold(PPNSCallBackUrlFailedResponse("Unknown Error"))(PPNSCallBackUrlFailedResponse) - ).recover { - case NonFatal(e) => throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") - } + ) + .recover { case NonFatal(e) => + throw new RuntimeException(s"Unexpected response from $externalServiceUri: ${e.getMessage}") + } } } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsController.scala b/app/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsController.scala index 1b6e96f..bb7d7d8 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsController.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsController.scala @@ -16,21 +16,22 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import java.util.UUID import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} +import scala.util.{Failure, Success, Try} -import play.api.libs.json.{JsValue, Json, JsSuccess, JsError} +import play.api.libs.json.{JsError, JsSuccess, JsValue, Json} import play.api.mvc._ -import uk.gov.hmrc.apisubscriptionfields.model._ +import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService -import scala.concurrent.Future -import scala.util.{Try,Success,Failure} -import java.util.UUID -import scala.concurrent.ExecutionContext import uk.gov.hmrc.apisubscriptionfields.utils.ApplicationLogger @Singleton -class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service: ApiFieldDefinitionsService)(implicit ec: ExecutionContext) extends CommonController with ApplicationLogger { +class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service: ApiFieldDefinitionsService)(implicit ec: ExecutionContext) + extends CommonController + with ApplicationLogger { import JsonFormatters._ @@ -46,11 +47,11 @@ class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service def validateFieldsDefinition(): Action[JsValue] = Action(parse.json) { request => Try(request.body.validate[FieldDefinitionsRequest]) match { case Success(JsSuccess(payload, _)) => Ok("") - case Success(JsError(errs)) => { - badRequestWithTag( (tag:UUID) => s"A JSON error occurred: [${tag.toString}] ${Json.prettyPrint(JsError.toJson(errs))}") + case Success(JsError(errs)) => { + badRequestWithTag((tag: UUID) => s"A JSON error occurred: [${tag.toString}] ${Json.prettyPrint(JsError.toJson(errs))}") } - case Failure(e) => { - badRequestWithTag{ (tag:UUID) => s"An error occurred during JSON validation: [${tag.toString}] ${e.getMessage}" } + case Failure(e) => { + badRequestWithTag { (tag: UUID) => s"An error occurred during JSON validation: [${tag.toString}] ${e.getMessage}" } } } } @@ -58,13 +59,13 @@ class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service def upsertFieldsDefinition(apiContext: ApiContext, apiVersion: ApiVersion): Action[JsValue] = Action.async(parse.json) { implicit request => withJsonBody[FieldDefinitionsRequest] { payload => service.upsert(apiContext, apiVersion, payload.fieldDefinitions) map { - case (response, true) => Created(Json.toJson(response)) + case (response, true) => Created(Json.toJson(response)) case (response, false) => Ok(Json.toJson(response)) } } recover recovery } - def getAllFieldsDefinitions: Action[AnyContent] = Action.async { _ => + def getAllFieldsDefinitions: Action[AnyContent] = Action.async { _ => service.getAll map (defs => Ok(Json.toJson(defs))) recover recovery } @@ -75,7 +76,7 @@ class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service def deleteFieldsDefinition(apiContext: ApiContext, apiVersion: ApiVersion): Action[AnyContent] = Action.async { _ => service.delete(apiContext, apiVersion) map { - case true => NoContent + case true => NoContent case false => notFoundResponse(apiContext, apiVersion) } recover recovery } @@ -83,7 +84,7 @@ class ApiFieldDefinitionsController @Inject() (cc: ControllerComponents, service private def asActionResult(eventualMaybeResponse: Future[Option[ApiFieldDefinitions]], apiContext: ApiContext, apiVersion: ApiVersion) = { eventualMaybeResponse map { case Some(subscriptionFields) => Ok(Json.toJson(subscriptionFields)) - case None => notFoundResponse(apiContext, apiVersion) + case None => notFoundResponse(apiContext, apiVersion) } recover recovery } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/controller/Binders.scala b/app/uk/gov/hmrc/apisubscriptionfields/controller/Binders.scala index abcdcfa..c4e7b64 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/controller/Binders.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/controller/Binders.scala @@ -16,36 +16,39 @@ package uk.gov.hmrc.apisubscriptionfields.controller -import play.api.mvc.PathBindable -import uk.gov.hmrc.apisubscriptionfields.model.{ApiContext,ApiVersion, ClientId, SubscriptionFieldsId} import java.{util => ju} -object Binders { - - implicit object apiContextPathBindable extends PathBindable.Parsing[ApiContext]( - ApiContext.apply, - _.value, - (key: String, e: Exception) => "Cannot parse parameter %s as ApiContext: %s".format(key, e.getMessage) - ) - - implicit object apiVersionPathBindable extends PathBindable.Parsing[ApiVersion]( - ApiVersion.apply, - _.value, - (key: String, e: Exception) => "Cannot parse parameter %s as ApiVersion: %s".format(key, e.getMessage) - ) - - implicit object clientIdPathBindable extends PathBindable.Parsing[ClientId]( - ClientId.apply, - _.value, - (key: String, e: Exception) => "Cannot parse parameter %s as ClientId: %s".format(key, e.getMessage) - ) - - implicit object subscriptionFieldsIdPathBindable extends PathBindable.Parsing[SubscriptionFieldsId]( - s => SubscriptionFieldsId(ju.UUID.fromString(s)), - _.value.toString, - (key: String, e: Exception) => "Cannot parse parameter %s as SubscriptionFieldsId: %s".format(key, e.getMessage) - ) -} +import play.api.mvc.PathBindable +import uk.gov.hmrc.apisubscriptionfields.model.{ApiContext, ApiVersion, ClientId, SubscriptionFieldsId} +object Binders { + implicit object apiContextPathBindable + extends PathBindable.Parsing[ApiContext]( + ApiContext.apply, + _.value, + (key: String, e: Exception) => "Cannot parse parameter %s as ApiContext: %s".format(key, e.getMessage) + ) + + implicit object apiVersionPathBindable + extends PathBindable.Parsing[ApiVersion]( + ApiVersion.apply, + _.value, + (key: String, e: Exception) => "Cannot parse parameter %s as ApiVersion: %s".format(key, e.getMessage) + ) + + implicit object clientIdPathBindable + extends PathBindable.Parsing[ClientId]( + ClientId.apply, + _.value, + (key: String, e: Exception) => "Cannot parse parameter %s as ClientId: %s".format(key, e.getMessage) + ) + + implicit object subscriptionFieldsIdPathBindable + extends PathBindable.Parsing[SubscriptionFieldsId]( + s => SubscriptionFieldsId(ju.UUID.fromString(s)), + _.value.toString, + (key: String, e: Exception) => "Cannot parse parameter %s as SubscriptionFieldsId: %s".format(key, e.getMessage) + ) +} diff --git a/app/uk/gov/hmrc/apisubscriptionfields/controller/CommonController.scala b/app/uk/gov/hmrc/apisubscriptionfields/controller/CommonController.scala index a1c3589..02da986 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/controller/CommonController.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/controller/CommonController.scala @@ -16,24 +16,24 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.Future +import scala.util.{Failure, Success, Try} + import play.api.libs.json._ import play.api.mvc.{Request, Result} +import uk.gov.hmrc.play.bootstrap.backend.controller.BackendBaseController + import uk.gov.hmrc.apisubscriptionfields.model.ErrorCode._ import uk.gov.hmrc.apisubscriptionfields.model.JsErrorResponse -import uk.gov.hmrc.play.bootstrap.backend.controller.BackendBaseController import uk.gov.hmrc.apisubscriptionfields.utils.ApplicationLogger -import scala.concurrent.Future -import scala.util.{Failure, Success, Try} - trait CommonController extends BackendBaseController with ApplicationLogger { - override protected def withJsonBody[T] - (f: (T) => Future[Result])(implicit request: Request[JsValue], m: Manifest[T], reads: Reads[T]): Future[Result] = { + override protected def withJsonBody[T](f: (T) => Future[Result])(implicit request: Request[JsValue], m: Manifest[T], reads: Reads[T]): Future[Result] = { Try(request.body.validate[T]) match { case Success(JsSuccess(payload, _)) => f(payload) - case Success(JsError(errs)) => jsonError(JsError.toJson(errs).toString()) - case Failure(e) => jsonError(e.getMessage) + case Success(JsError(errs)) => jsonError(JsError.toJson(errs).toString()) + case Failure(e) => jsonError(e.getMessage) } } @@ -42,8 +42,8 @@ trait CommonController extends BackendBaseController with ApplicationLogger { Future.successful(UnprocessableEntity(JsErrorResponse(INVALID_REQUEST_PAYLOAD, "A JSON error occurred"))) } - def recovery: PartialFunction[Throwable, Result] = { - case e => handleException(e) + def recovery: PartialFunction[Throwable, Result] = { case e => + handleException(e) } private[controller] def handleException(e: Throwable) = { diff --git a/app/uk/gov/hmrc/apisubscriptionfields/controller/Requests.scala b/app/uk/gov/hmrc/apisubscriptionfields/controller/Requests.scala index d300941..1b35976 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/controller/Requests.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/controller/Requests.scala @@ -16,15 +16,15 @@ package uk.gov.hmrc.apisubscriptionfields.controller -import uk.gov.hmrc.apisubscriptionfields.model.Types._ -import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinition import cats.data.NonEmptyList +import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinition +import uk.gov.hmrc.apisubscriptionfields.model.Types._ + private[controller] case class SubscriptionFieldsRequest(fields: Fields) private[controller] case class FieldDefinitionsRequest(fieldDefinitions: NonEmptyList[FieldDefinition]) - object SubscriptionFieldsRequest { import play.api.libs.json._ import be.venneborg.refined.play.RefinedJsonFormats._ diff --git a/app/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsController.scala b/app/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsController.scala index c820ed8..2d76f8c 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsController.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsController.scala @@ -17,17 +17,17 @@ package uk.gov.hmrc.apisubscriptionfields.controller import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} + import play.api.libs.json._ import play.api.mvc._ + import uk.gov.hmrc.apisubscriptionfields.model.ErrorCode._ import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.service.SubscriptionFieldsService -import scala.concurrent.Future -import scala.concurrent.ExecutionContext - @Singleton -class SubscriptionFieldsController @Inject()(cc: ControllerComponents, service: SubscriptionFieldsService)(implicit ec: ExecutionContext) extends CommonController { +class SubscriptionFieldsController @Inject() (cc: ControllerComponents, service: SubscriptionFieldsService)(implicit ec: ExecutionContext) extends CommonController { import JsonFormatters._ @@ -69,14 +69,14 @@ class SubscriptionFieldsController @Inject()(cc: ControllerComponents, service: private def asActionResult[T](eventualMaybeResponse: Future[Option[T]], notFoundMessage: String)(implicit writes: Writes[T]) = { eventualMaybeResponse map { case Some(payload) => Ok(Json.toJson(payload)) - case None => notFoundResponse(notFoundMessage) + case None => notFoundResponse(notFoundMessage) } recover recovery } private def asBulkActionResult(eventualMaybeResponse: Future[Option[BulkSubscriptionFieldsResponse]], notFoundMessage: String) = { eventualMaybeResponse map { case Some(subscriptionFields) => Ok(Json.toJson(subscriptionFields)) - case None => notFoundResponse(notFoundMessage) + case None => notFoundResponse(notFoundMessage) } recover recovery } @@ -84,33 +84,34 @@ class SubscriptionFieldsController @Inject()(cc: ControllerComponents, service: import JsonFormatters._ withJsonBody[SubscriptionFieldsRequest] { payload => - if(payload.fields.isEmpty) { + if (payload.fields.isEmpty) { Future.successful(UnprocessableEntity(JsErrorResponse(INVALID_REQUEST_PAYLOAD, "At least one field must be specified"))) - } - else { - service.upsert(clientId, apiContext, apiVersion, payload.fields).map( _ match { - case NotFoundSubsFieldsUpsertResponse => BadRequest(Json.toJson("reason" -> "field definitions not found")) // TODO - case FailedValidationSubsFieldsUpsertResponse(fieldErrorMessages) => - BadRequest(Json.toJson(fieldErrorMessages)) - case SuccessfulSubsFieldsUpsertResponse(response, true) => Created(Json.toJson(response)) - case SuccessfulSubsFieldsUpsertResponse(response, false) => - Ok(Json.toJson(response)) - }) - .recover(recovery) + } else { + service + .upsert(clientId, apiContext, apiVersion, payload.fields) + .map(_ match { + case NotFoundSubsFieldsUpsertResponse => BadRequest(Json.toJson("reason" -> "field definitions not found")) // TODO + case FailedValidationSubsFieldsUpsertResponse(fieldErrorMessages) => + BadRequest(Json.toJson(fieldErrorMessages)) + case SuccessfulSubsFieldsUpsertResponse(response, true) => Created(Json.toJson(response)) + case SuccessfulSubsFieldsUpsertResponse(response, false) => + Ok(Json.toJson(response)) + }) + .recover(recovery) } } } def deleteSubscriptionFields(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion): Action[AnyContent] = Action.async { _ => service.delete(clientId, apiContext, apiVersion) map { - case true => NoContent + case true => NoContent case false => notFoundResponse(notFoundMessage(clientId, apiContext, apiVersion)) } recover recovery } def deleteAllSubscriptionFieldsForClient(clientId: ClientId): Action[AnyContent] = Action.async { _ => service.delete(clientId) map { - case true => NoContent + case true => NoContent case false => notFoundResponse(clientIdNotFoundMessage(clientId)) } recover recovery } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirements.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirements.scala index 6059ed7..4779a13 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirements.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirements.scala @@ -18,21 +18,18 @@ package uk.gov.hmrc.apisubscriptionfields.model sealed trait DevhubAccessRequirement object DevhubAccessRequirement { - final val Default: DevhubAccessRequirement = Anyone + final val Default: DevhubAccessRequirement = Anyone - case object NoOne extends DevhubAccessRequirement - case object AdminOnly extends DevhubAccessRequirement - case object Anyone extends DevhubAccessRequirement + case object NoOne extends DevhubAccessRequirement + case object AdminOnly extends DevhubAccessRequirement + case object Anyone extends DevhubAccessRequirement } -case class DevhubAccessRequirements private ( - val read: DevhubAccessRequirement, - val write: DevhubAccessRequirement) { - def satisfiesRead(dal: DevhubAccessLevel): Boolean = dal.satisfiesRequirement(read) // ReadWrite will be at least as strict. +case class DevhubAccessRequirements private (val read: DevhubAccessRequirement, val write: DevhubAccessRequirement) { + def satisfiesRead(dal: DevhubAccessLevel): Boolean = dal.satisfiesRequirement(read) // ReadWrite will be at least as strict. def satisfiesWrite(dal: DevhubAccessLevel): Boolean = dal.satisfiesRequirement(write) } - object DevhubAccessRequirements { import DevhubAccessRequirement._ @@ -41,10 +38,10 @@ object DevhubAccessRequirements { // Do not allow greater restrictions on read than on write // - it would make no sense to allow NoOne read but everyone write or developer write and admin read // - def apply(read: DevhubAccessRequirement, write: DevhubAccessRequirement = DevhubAccessRequirement.Default): DevhubAccessRequirements = (read,write) match { + def apply(read: DevhubAccessRequirement, write: DevhubAccessRequirement = DevhubAccessRequirement.Default): DevhubAccessRequirements = (read, write) match { case (NoOne, _) => new DevhubAccessRequirements(NoOne, NoOne) - case (AdminOnly, Anyone) => new DevhubAccessRequirements(AdminOnly,AdminOnly) - case _ => new DevhubAccessRequirements(read,write) + case (AdminOnly, Anyone) => new DevhubAccessRequirements(AdminOnly, AdminOnly) + case _ => new DevhubAccessRequirements(read, write) } } @@ -53,18 +50,17 @@ object AccessRequirements { final val Default = AccessRequirements(devhub = DevhubAccessRequirements.Default) } - sealed trait DevhubAccessLevel { def satisfiesRequirement(requirement: DevhubAccessRequirement): Boolean = DevhubAccessLevel.satisfies(requirement)(this) } -object DevhubAccessLevel { - case object Developer extends DevhubAccessLevel +object DevhubAccessLevel { + case object Developer extends DevhubAccessLevel case object Admininstator extends DevhubAccessLevel import DevhubAccessRequirement._ def satisfies(requirement: DevhubAccessRequirement)(actual: DevhubAccessLevel): Boolean = (requirement, actual) match { - case (NoOne, _) => false - case (AdminOnly, Developer) => false - case _ => true + case (NoOne, _) => false + case (AdminOnly, Developer) => false + case _ => true } } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatters.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatters.scala index e2ca4a3..e33fa37 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatters.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatters.scala @@ -16,16 +16,16 @@ package uk.gov.hmrc.apisubscriptionfields.model - import cats.data.{NonEmptyList => NEL} import julienrf.json.derived -import play.api.libs.json._ -import play.api.libs.functional.syntax._ import julienrf.json.derived.TypeTagSetting.ShortClassName -import Types._ -import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType.FieldDefinitionType -import Types._ + +import play.api.libs.functional.syntax._ import play.api.libs.json.Json.JsValueWrapper +import play.api.libs.json._ + +import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType.FieldDefinitionType +import uk.gov.hmrc.apisubscriptionfields.model.Types._ trait NonEmptyListFormatters { @@ -34,8 +34,8 @@ trait NonEmptyListFormatters { .of[List[A]] .collect( JsonValidationError("expected a NonEmptyList but got an empty list") - ) { - case head :: tail => NEL(head, tail) + ) { case head :: tail => + NEL(head, tail) } implicit def nelWrites[A](implicit w: Writes[A]): Writes[NEL[A]] = @@ -47,30 +47,30 @@ trait NonEmptyListFormatters { object NonEmptyListFormatters extends NonEmptyListFormatters trait AccessRequirementsFormatters { - import DevhubAccessRequirement._ + import DevhubAccessRequirement._ def ignoreDefaultField[T](value: T, default: T, jsonFieldName: String)(implicit w: Writes[T]) = - if(value == default) None else Some((jsonFieldName, Json.toJsFieldJsValueWrapper(value))) + if (value == default) None else Some((jsonFieldName, Json.toJsFieldJsValueWrapper(value))) implicit val DevhubAccessRequirementFormat: Format[DevhubAccessRequirement] = new Format[DevhubAccessRequirement] { override def writes(o: DevhubAccessRequirement): JsValue = JsString(o match { case AdminOnly => "adminOnly" - case Anyone => "anyone" - case NoOne => "noOne" + case Anyone => "anyone" + case NoOne => "noOne" }) override def reads(json: JsValue): JsResult[DevhubAccessRequirement] = json match { case JsString("adminOnly") => JsSuccess(AdminOnly) - case JsString("anyone") => JsSuccess(Anyone) - case JsString("noOne") => JsSuccess(NoOne) - case _ => JsError("Not a recognized DevhubAccessRequirement") + case JsString("anyone") => JsSuccess(Anyone) + case JsString("noOne") => JsSuccess(NoOne) + case _ => JsError("Not a recognized DevhubAccessRequirement") } } implicit val DevhubAccessRequirementsReads: Reads[DevhubAccessRequirements] = ( ((JsPath \ "read").read[DevhubAccessRequirement] or Reads.pure(DevhubAccessRequirement.Default)) and - ((JsPath \ "write").read[DevhubAccessRequirement] or Reads.pure(DevhubAccessRequirement.Default)) + ((JsPath \ "write").read[DevhubAccessRequirement] or Reads.pure(DevhubAccessRequirement.Default)) )(DevhubAccessRequirements.apply _) implicit val DevhubAccessRequirementsWrites: OWrites[DevhubAccessRequirements] = new OWrites[DevhubAccessRequirements] { @@ -78,8 +78,8 @@ trait AccessRequirementsFormatters { Json.obj( ( ignoreDefaultField(requirements.read, DevhubAccessRequirement.Default, "read") :: - ignoreDefaultField(requirements.write, DevhubAccessRequirement.Default, "write") :: - List.empty[Option[(String, JsValueWrapper)]] + ignoreDefaultField(requirements.write, DevhubAccessRequirement.Default, "write") :: + List.empty[Option[(String, JsValueWrapper)]] ).filterNot(_.isEmpty).map(_.get): _* ) } @@ -92,20 +92,18 @@ trait AccessRequirementsFormatters { object AccessRequirementsFormatters extends AccessRequirementsFormatters -trait JsonFormatters - extends NonEmptyListFormatters - with AccessRequirementsFormatters { +trait JsonFormatters extends NonEmptyListFormatters with AccessRequirementsFormatters { import be.venneborg.refined.play.RefinedJsonFormats._ import eu.timepit.refined.api.Refined import eu.timepit.refined.auto._ import play.api.libs.json._ - implicit val ClientIdJF = Json.valueFormat[ClientId] - implicit val BoxIdJF = Json.valueFormat[BoxId] + implicit val ClientIdJF = Json.valueFormat[ClientId] + implicit val BoxIdJF = Json.valueFormat[BoxId] implicit val SubscriptionFieldsIdjsonFormat = Json.valueFormat[SubscriptionFieldsId] - implicit val ApiContextJF = Json.valueFormat[ApiContext] - implicit val ApiVersionJF = Json.valueFormat[ApiVersion] + implicit val ApiContextJF = Json.valueFormat[ApiContext] + implicit val ApiVersionJF = Json.valueFormat[ApiVersion] implicit val FieldNameFormat = formatRefined[String, FieldNameRegex, Refined] @@ -119,43 +117,43 @@ trait JsonFormatters implicit val FieldDefinitionReads: Reads[FieldDefinition] = ( (JsPath \ "name").read[FieldName] and - (JsPath \ "description").read[String] and - ((JsPath \ "hint").read[String] or Reads.pure("")) and - (JsPath \ "type").read[FieldDefinitionType] and - ((JsPath \ "shortDescription").read[String] or Reads.pure("")) and - (JsPath \ "validation").readNullable[ValidationGroup] and - ((JsPath \ "access").read[AccessRequirements] or Reads.pure(AccessRequirements.Default)) + (JsPath \ "description").read[String] and + ((JsPath \ "hint").read[String] or Reads.pure("")) and + (JsPath \ "type").read[FieldDefinitionType] and + ((JsPath \ "shortDescription").read[String] or Reads.pure("")) and + (JsPath \ "validation").readNullable[ValidationGroup] and + ((JsPath \ "access").read[AccessRequirements] or Reads.pure(AccessRequirements.Default)) )(FieldDefinition.apply _) implicit val FieldDefinitionWrites: Writes[FieldDefinition] = new Writes[FieldDefinition] { - def dropTail[A,B,C,D,E,F,G]( t: Tuple7[A,B,C,D,E,F,G] ): Tuple6[A,B,C,D,E,F] = (t._1, t._2, t._3, t._4, t._5, t._6) + def dropTail[A, B, C, D, E, F, G](t: Tuple7[A, B, C, D, E, F, G]): Tuple6[A, B, C, D, E, F] = (t._1, t._2, t._3, t._4, t._5, t._6) // This allows us to hide default AccessRequirements from JSON - as this is a rarely used field // but not one that business logic would want as an optional field and require getOrElse everywhere. override def writes(o: FieldDefinition): JsValue = { val common = - (JsPath \ "name").write[FieldName] and + (JsPath \ "name").write[FieldName] and (JsPath \ "description").write[String] and (JsPath \ "hint").write[String] and (JsPath \ "type").write[FieldDefinitionType] and (JsPath \ "shortDescription").write[String] and (JsPath \ "validation").writeNullable[ValidationGroup] - (if(o.access == AccessRequirements.Default) { - (common)(unlift(FieldDefinition.unapply).andThen(dropTail)) - } else { - (common and (JsPath \ "access").write[AccessRequirements])(unlift(FieldDefinition.unapply)) - }).writes(o) + (if (o.access == AccessRequirements.Default) { + (common)(unlift(FieldDefinition.unapply).andThen(dropTail)) + } else { + (common and (JsPath \ "access").write[AccessRequirements])(unlift(FieldDefinition.unapply)) + }).writes(o) } } - implicit val ApiFieldDefinitionsJF: OFormat[ApiFieldDefinitions] = Json.format[ApiFieldDefinitions] - implicit val BulkApiFieldDefinitionsResponseJF = Json.format[BulkApiFieldDefinitionsResponse] + implicit val ApiFieldDefinitionsJF: OFormat[ApiFieldDefinitions] = Json.format[ApiFieldDefinitions] + implicit val BulkApiFieldDefinitionsResponseJF = Json.format[BulkApiFieldDefinitionsResponse] implicit val SubsFieldValidationResponseJF: OFormat[SubsFieldValidationResponse] = derived.withTypeTag.oformat(ShortClassName) - implicit val InvalidSubsFieldValidationResponseJF = Json.format[InvalidSubsFieldValidationResponse] + implicit val InvalidSubsFieldValidationResponseJF = Json.format[InvalidSubsFieldValidationResponse] - implicit val SubscriptionFieldsJF = Json.format[SubscriptionFields] + implicit val SubscriptionFieldsJF = Json.format[SubscriptionFields] implicit val BulkSubscriptionFieldsResponseJF = Json.format[BulkSubscriptionFieldsResponse] } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/Model.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/Model.scala index b5a653e..61806a4 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/Model.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/Model.scala @@ -17,10 +17,10 @@ package uk.gov.hmrc.apisubscriptionfields.model import cats.data.{NonEmptyList => NEL} +import org.apache.commons.validator.routines.{DomainValidator, UrlValidator} + import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType.FieldDefinitionType -import org.apache.commons.validator.routines.UrlValidator -import Types._ -import org.apache.commons.validator.routines.DomainValidator +import uk.gov.hmrc.apisubscriptionfields.model.Types._ sealed trait ValidationRule { def validate(value: FieldValue): Boolean = { @@ -37,7 +37,7 @@ case class RegexValidationRule(regex: RegexExpr) extends ValidationRule { // Taken from: https://stackoverflow.com/a/5078838 case object UrlValidationRule extends ValidationRule { DomainValidator.updateTLDOverride(DomainValidator.ArrayType.GENERIC_PLUS, Array("mdtp")); - private val schemes = Array("http","https") + private val schemes = Array("http", "https") private lazy val urlValidator = new org.apache.commons.validator.routines.UrlValidator(schemes, UrlValidator.ALLOW_LOCAL_URLS) def validateAgainstRule(value: FieldValue): Boolean = { @@ -51,20 +51,21 @@ object FieldDefinitionType extends Enumeration { type FieldDefinitionType = Value @deprecated("We don't use URL type for any validation", since = "0.5x") - val URL = Value("URL") + val URL = Value("URL") val SECURE_TOKEN = Value("SecureToken") - val STRING = Value("STRING") - val PPNS_FIELD = Value("PPNSField") + val STRING = Value("STRING") + val PPNS_FIELD = Value("PPNSField") } case class FieldDefinition( - name: FieldName, - description: String, - hint: String = "", - `type`: FieldDefinitionType, - shortDescription: String, - validation: Option[ValidationGroup] = None, - access: AccessRequirements = AccessRequirements.Default) + name: FieldName, + description: String, + hint: String = "", + `type`: FieldDefinitionType, + shortDescription: String, + validation: Option[ValidationGroup] = None, + access: AccessRequirements = AccessRequirements.Default +) case class ApiFieldDefinitions(apiContext: ApiContext, apiVersion: ApiVersion, fieldDefinitions: NEL[FieldDefinition]) diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/Responses.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/Responses.scala index 95d4038..daaaff4 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/Responses.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/Responses.scala @@ -18,11 +18,12 @@ package uk.gov.hmrc.apisubscriptionfields.model import play.api.libs.json.Json.JsValueWrapper import play.api.libs.json.{JsObject, Json} -import Types._ + +import uk.gov.hmrc.apisubscriptionfields.model.Types._ sealed trait SubsFieldsUpsertResponse -case object NotFoundSubsFieldsUpsertResponse extends SubsFieldsUpsertResponse -case class FailedValidationSubsFieldsUpsertResponse(errorResponses: Map[FieldName, String]) extends SubsFieldsUpsertResponse +case object NotFoundSubsFieldsUpsertResponse extends SubsFieldsUpsertResponse +case class FailedValidationSubsFieldsUpsertResponse(errorResponses: Map[FieldName, String]) extends SubsFieldsUpsertResponse case class SuccessfulSubsFieldsUpsertResponse(wrapped: SubscriptionFields, isInsert: Boolean) extends SubsFieldsUpsertResponse case class BulkSubscriptionFieldsResponse(subscriptions: Seq[SubscriptionFields]) @@ -30,25 +31,25 @@ case class BulkSubscriptionFieldsResponse(subscriptions: Seq[SubscriptionFields] case class BulkApiFieldDefinitionsResponse(apis: Seq[ApiFieldDefinitions]) sealed trait SubsFieldValidationResponse -case object ValidSubsFieldValidationResponse extends SubsFieldValidationResponse +case object ValidSubsFieldValidationResponse extends SubsFieldValidationResponse case class InvalidSubsFieldValidationResponse(errorResponses: Map[FieldName, String]) extends SubsFieldValidationResponse sealed trait PPNSCallBackUrlValidationResponse -case object PPNSCallBackUrlSuccessResponse extends PPNSCallBackUrlValidationResponse +case object PPNSCallBackUrlSuccessResponse extends PPNSCallBackUrlValidationResponse case class PPNSCallBackUrlFailedResponse(errorMsg: String) extends PPNSCallBackUrlValidationResponse object ErrorCode extends Enumeration { type ErrorCode = Value val INVALID_REQUEST_PAYLOAD = Value("INVALID_REQUEST_PAYLOAD") - val UNKNOWN_ERROR = Value("UNKNOWN_ERROR") - val NOT_FOUND_CODE = Value("NOT_FOUND") + val UNKNOWN_ERROR = Value("UNKNOWN_ERROR") + val NOT_FOUND_CODE = Value("NOT_FOUND") } object JsErrorResponse { def apply(errorCode: ErrorCode.Value, message: JsValueWrapper): JsObject = Json.obj( - "code" -> errorCode.toString, + "code" -> errorCode.toString, "message" -> message ) } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/Shared.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/Shared.scala index e35827d..001865a 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/Shared.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/Shared.scala @@ -18,7 +18,6 @@ package uk.gov.hmrc.apisubscriptionfields.model import java.{util => ju} - case class ClientId(value: String) extends AnyVal case class ApiContext(value: String) extends AnyVal diff --git a/app/uk/gov/hmrc/apisubscriptionfields/model/Types.scala b/app/uk/gov/hmrc/apisubscriptionfields/model/Types.scala index 1632276..03c7569 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/model/Types.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/model/Types.scala @@ -24,7 +24,7 @@ object Types { type RegexExpr = String Refined Regex type FieldNameRegex = MatchesRegex[W.`"^[a-zA-Z]+$"`.T] - type FieldName = Refined[String,FieldNameRegex] + type FieldName = Refined[String, FieldNameRegex] type FieldValue = String diff --git a/app/uk/gov/hmrc/apisubscriptionfields/repository/FieldDefinitionRepository.scala b/app/uk/gov/hmrc/apisubscriptionfields/repository/FieldDefinitionRepository.scala index 27f58c0..9c4fd00 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/repository/FieldDefinitionRepository.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/repository/FieldDefinitionRepository.scala @@ -16,6 +16,9 @@ package uk.gov.hmrc.apisubscriptionfields.repository +import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} + import akka.stream.Materializer import com.google.inject.ImplementedBy import org.bson.codecs.configuration.CodecRegistries.{fromCodecs, fromRegistries} @@ -23,16 +26,13 @@ import org.mongodb.scala.model.Filters.{and, equal} import org.mongodb.scala.model.Indexes.ascending import org.mongodb.scala.model.{Filters, IndexModel, IndexOptions} import org.mongodb.scala.{MongoClient, MongoCollection} -import play.api.libs.json._ -import uk.gov.hmrc.apisubscriptionfields.model.JsonFormatters.ApiFieldDefinitionsJF -import uk.gov.hmrc.apisubscriptionfields.model.Types._ -import uk.gov.hmrc.apisubscriptionfields.model._ -import uk.gov.hmrc.apisubscriptionfields.utils.ApplicationLogger + import uk.gov.hmrc.mongo.MongoComponent import uk.gov.hmrc.mongo.play.json.{Codecs, CollectionFactory, PlayMongoRepository} -import javax.inject.{Inject, Singleton} -import scala.concurrent.{ExecutionContext, Future} +import uk.gov.hmrc.apisubscriptionfields.model.Types._ +import uk.gov.hmrc.apisubscriptionfields.model._ +import uk.gov.hmrc.apisubscriptionfields.utils.ApplicationLogger @ImplementedBy(classOf[ApiFieldDefinitionsMongoRepository]) trait ApiFieldDefinitionsRepository { @@ -47,19 +47,21 @@ trait ApiFieldDefinitionsRepository { } @Singleton -class ApiFieldDefinitionsMongoRepository @Inject() (mongo: MongoComponent) - (implicit ec: ExecutionContext, val mat: Materializer) - extends PlayMongoRepository[ApiFieldDefinitions]( - collectionName = "fieldsDefinitions", - mongoComponent = mongo, - domainFormat = JsonFormatters.ApiFieldDefinitionsJF, - indexes = Seq( - IndexModel(ascending(List("apiContext", "apiVersion"): _*), - IndexOptions() - .name("apiContext-apiVersion_index") - .background(true) - .unique(true)) - )) +class ApiFieldDefinitionsMongoRepository @Inject() (mongo: MongoComponent)(implicit ec: ExecutionContext, val mat: Materializer) + extends PlayMongoRepository[ApiFieldDefinitions]( + collectionName = "fieldsDefinitions", + mongoComponent = mongo, + domainFormat = JsonFormatters.ApiFieldDefinitionsJF, + indexes = Seq( + IndexModel( + ascending(List("apiContext", "apiVersion"): _*), + IndexOptions() + .name("apiContext-apiVersion_index") + .background(true) + .unique(true) + ) + ) + ) with ApiFieldDefinitionsRepository with ApplicationLogger { @@ -80,16 +82,18 @@ class ApiFieldDefinitionsMongoRepository @Inject() (mongo: MongoComponent) ) def save(definitions: ApiFieldDefinitions): Future[(ApiFieldDefinitions, IsInsert)] = { - val query = and(equal("apiContext", Codecs.toBson(definitions.apiContext.value)), - equal("apiVersion", Codecs.toBson(definitions.apiVersion.value))) + val query = and(equal("apiContext", Codecs.toBson(definitions.apiContext.value)), equal("apiVersion", Codecs.toBson(definitions.apiVersion.value))) collection.find(query).headOption flatMap { case Some(_: ApiFieldDefinitions) => for { - updatedDefinitions <- collection.replaceOne( - filter = query, - replacement = definitions - ).toFuture().map(_ => definitions) + updatedDefinitions <- collection + .replaceOne( + filter = query, + replacement = definitions + ) + .toFuture() + .map(_ => definitions) } yield (updatedDefinitions, false) case None => @@ -100,8 +104,7 @@ class ApiFieldDefinitionsMongoRepository @Inject() (mongo: MongoComponent) } override def fetch(apiContext: ApiContext, apiVersion: ApiVersion): Future[Option[ApiFieldDefinitions]] = { - collection.find(Filters.and(equal("apiContext", Codecs.toBson(apiContext.value)), - equal("apiVersion", Codecs.toBson(apiVersion.value)))).headOption() + collection.find(Filters.and(equal("apiContext", Codecs.toBson(apiContext.value)), equal("apiVersion", Codecs.toBson(apiVersion.value)))).headOption() } override def fetchAll(): Future[List[ApiFieldDefinitions]] = { @@ -109,8 +112,8 @@ class ApiFieldDefinitionsMongoRepository @Inject() (mongo: MongoComponent) } override def delete(apiContext: ApiContext, apiVersion: ApiVersion): Future[Boolean] = { - collection.deleteOne(Filters.and(equal("apiContext", Codecs.toBson(apiContext.value)), - equal("apiVersion", Codecs.toBson(apiVersion.value)))) + collection + .deleteOne(Filters.and(equal("apiContext", Codecs.toBson(apiContext.value)), equal("apiVersion", Codecs.toBson(apiVersion.value)))) .toFuture() .map(_.getDeletedCount > 0) } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepository.scala b/app/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepository.scala index b9ea88c..00f3f1f 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepository.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepository.scala @@ -17,22 +17,23 @@ package uk.gov.hmrc.apisubscriptionfields.repository import java.util.UUID - import javax.inject.{Inject, Singleton} -import com.google.inject.ImplementedBy -import uk.gov.hmrc.apisubscriptionfields.model._ -import Types.{Fields, IsInsert} +import scala.concurrent.{ExecutionContext, Future} + import akka.stream.Materializer +import com.google.inject.ImplementedBy import org.bson.codecs.configuration.CodecRegistries.{fromCodecs, fromRegistries} import org.mongodb.scala.model.Filters.{and, equal} -import org.mongodb.scala.{MongoClient, MongoCollection} -import org.mongodb.scala.model.{IndexModel, IndexOptions} import org.mongodb.scala.model.Indexes.ascending +import org.mongodb.scala.model.{IndexModel, IndexOptions} +import org.mongodb.scala.{MongoClient, MongoCollection} + import uk.gov.hmrc.mongo.MongoComponent +import uk.gov.hmrc.mongo.play.json.{Codecs, CollectionFactory, PlayMongoRepository} -import scala.concurrent.{ExecutionContext, Future} +import uk.gov.hmrc.apisubscriptionfields.model.Types.{Fields, IsInsert} +import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.utils.ApplicationLogger -import uk.gov.hmrc.mongo.play.json.{Codecs, CollectionFactory, PlayMongoRepository} @ImplementedBy(classOf[SubscriptionFieldsMongoRepository]) trait SubscriptionFieldsRepository { @@ -55,30 +56,35 @@ class UUIDCreator { } @Singleton -class SubscriptionFieldsMongoRepository @Inject()(mongo: MongoComponent, uuidCreator: UUIDCreator) - (implicit ec: ExecutionContext, val mat: Materializer) - extends PlayMongoRepository[SubscriptionFields]( - collectionName = "subscriptionFields", - mongoComponent = mongo, - domainFormat = JsonFormatters.SubscriptionFieldsJF, - indexes = Seq( - IndexModel(ascending(List("clientId", "apiContext", "apiVersion"): _*), - IndexOptions() - .name("clientId-apiContext-apiVersion_Index") - .unique(true)), - IndexModel(ascending("clientId"), - IndexOptions() - .name("clientIdIndex") - .unique(false)), - IndexModel(ascending("fieldsId"), - IndexOptions() - .name("fieldsIdIndex") - .unique(true)) - )) - - with SubscriptionFieldsRepository - with ApplicationLogger - with JsonFormatters { +class SubscriptionFieldsMongoRepository @Inject() (mongo: MongoComponent, uuidCreator: UUIDCreator)(implicit ec: ExecutionContext, val mat: Materializer) + extends PlayMongoRepository[SubscriptionFields]( + collectionName = "subscriptionFields", + mongoComponent = mongo, + domainFormat = JsonFormatters.SubscriptionFieldsJF, + indexes = Seq( + IndexModel( + ascending(List("clientId", "apiContext", "apiVersion"): _*), + IndexOptions() + .name("clientId-apiContext-apiVersion_Index") + .unique(true) + ), + IndexModel( + ascending("clientId"), + IndexOptions() + .name("clientIdIndex") + .unique(false) + ), + IndexModel( + ascending("fieldsId"), + IndexOptions() + .name("fieldsIdIndex") + .unique(true) + ) + ) + ) + with SubscriptionFieldsRepository + with ApplicationLogger + with JsonFormatters { override lazy val collection: MongoCollection[SubscriptionFields] = CollectionFactory @@ -96,25 +102,29 @@ class SubscriptionFieldsMongoRepository @Inject()(mongo: MongoComponent, uuidCre ) ) - override def saveAtomic(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, fields: Fields): Future[(SubscriptionFields, IsInsert)] = { - val query = and(equal("clientId", Codecs.toBson(clientId.value)), + val query = and( + equal("clientId", Codecs.toBson(clientId.value)), equal("apiContext", Codecs.toBson(apiContext.value)), - equal("apiVersion", Codecs.toBson(apiVersion.value))) + equal("apiVersion", Codecs.toBson(apiVersion.value)) + ) collection.find(query).headOption flatMap { case Some(subscription: SubscriptionFields) => val updatedSubscription = subscription.copy(fields = fields) for { - updatedDefinitions <- collection.replaceOne( - filter = query, - replacement = updatedSubscription - ).toFuture().map(_ => updatedSubscription) + updatedDefinitions <- collection + .replaceOne( + filter = query, + replacement = updatedSubscription + ) + .toFuture() + .map(_ => updatedSubscription) } yield (updatedDefinitions, false) case None => val subscriptionFieldsId = SubscriptionFieldsId(uuidCreator.uuid()) - val subscription = SubscriptionFields(clientId, apiContext, apiVersion, subscriptionFieldsId, fields) + val subscription = SubscriptionFields(clientId, apiContext, apiVersion, subscriptionFieldsId, fields) for { newSubscriptionFields <- collection.insertOne(subscription).toFuture().map(_ => subscription) } yield (newSubscriptionFields, true) @@ -122,9 +132,11 @@ class SubscriptionFieldsMongoRepository @Inject()(mongo: MongoComponent, uuidCre } override def fetch(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion): Future[Option[SubscriptionFields]] = { - val query = and(equal("clientId", Codecs.toBson(clientId.value)), + val query = and( + equal("clientId", Codecs.toBson(clientId.value)), equal("apiContext", Codecs.toBson(apiContext.value)), - equal("apiVersion", Codecs.toBson(apiVersion.value))) + equal("apiVersion", Codecs.toBson(apiVersion.value)) + ) collection.find(query).headOption() } @@ -144,17 +156,21 @@ class SubscriptionFieldsMongoRepository @Inject()(mongo: MongoComponent, uuidCre } override def delete(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion): Future[Boolean] = { - val query = and(equal("clientId", Codecs.toBson(clientId.value)), + val query = and( + equal("clientId", Codecs.toBson(clientId.value)), equal("apiContext", Codecs.toBson(apiContext.value)), - equal("apiVersion", Codecs.toBson(apiVersion.value))) - collection.deleteOne(query) + equal("apiVersion", Codecs.toBson(apiVersion.value)) + ) + collection + .deleteOne(query) .toFuture() .map(_.getDeletedCount > 0) } override def delete(clientId: ClientId): Future[Boolean] = { val query = equal("clientId", Codecs.toBson(clientId.value)) - collection.deleteMany(query) + collection + .deleteMany(query) .toFuture() .map(_.getDeletedCount > 0) } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsService.scala b/app/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsService.scala index 1e950ab..2376540 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsService.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsService.scala @@ -17,11 +17,12 @@ package uk.gov.hmrc.apisubscriptionfields.service import javax.inject.{Inject, Singleton} -import uk.gov.hmrc.apisubscriptionfields.model._ -import Types._ -import scala.concurrent.Future +import scala.concurrent.{ExecutionContext, Future} + import cats.data.NonEmptyList -import scala.concurrent.ExecutionContext + +import uk.gov.hmrc.apisubscriptionfields.model.Types._ +import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.repository.ApiFieldDefinitionsRepository @Singleton diff --git a/app/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationService.scala b/app/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationService.scala index 6a4a2b2..5ec518b 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationService.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationService.scala @@ -16,37 +16,31 @@ package uk.gov.hmrc.apisubscriptionfields.service - -import uk.gov.hmrc.apisubscriptionfields.connector.PushPullNotificationServiceConnector import javax.inject.{Inject, Singleton} -import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinition -import uk.gov.hmrc.apisubscriptionfields.model.Types.FieldValue - -import scala.concurrent.Future -import uk.gov.hmrc.apisubscriptionfields.model._ +import scala.concurrent.{ExecutionContext, Future} -import scala.concurrent.ExecutionContext import uk.gov.hmrc.http.HeaderCarrier +import uk.gov.hmrc.apisubscriptionfields.connector.PushPullNotificationServiceConnector +import uk.gov.hmrc.apisubscriptionfields.model.Types.FieldValue +import uk.gov.hmrc.apisubscriptionfields.model.{FieldDefinition, _} + @Singleton -class PushPullNotificationService @Inject()(ppnsConnector: PushPullNotificationServiceConnector)(implicit ec: ExecutionContext) { - def makeBoxName(apiContext: ApiContext, apiVersion: ApiVersion, fieldDefinition: FieldDefinition) : String = { +class PushPullNotificationService @Inject() (ppnsConnector: PushPullNotificationServiceConnector)(implicit ec: ExecutionContext) { + def makeBoxName(apiContext: ApiContext, apiVersion: ApiVersion, fieldDefinition: FieldDefinition): String = { val separator = "##" s"${apiContext.value}${separator}${apiVersion.value}${separator}${fieldDefinition.name.value}" } - def subscribeToPPNS(clientId: ClientId, - apiContext: ApiContext, - apiVersion: ApiVersion, - oFieldValue: Option[FieldValue], - fieldDefinition: FieldDefinition) - (implicit hc: HeaderCarrier): Future[PPNSCallBackUrlValidationResponse] = { + def subscribeToPPNS(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, oFieldValue: Option[FieldValue], fieldDefinition: FieldDefinition)(implicit + hc: HeaderCarrier + ): Future[PPNSCallBackUrlValidationResponse] = { for { - boxId <- ppnsConnector.ensureBoxIsCreated(makeBoxName(apiContext, apiVersion, fieldDefinition), clientId) + boxId <- ppnsConnector.ensureBoxIsCreated(makeBoxName(apiContext, apiVersion, fieldDefinition), clientId) result <- oFieldValue match { - case Some(value) => ppnsConnector.updateCallBackUrl (clientId, boxId, value) - case None => Future.successful(PPNSCallBackUrlSuccessResponse) - } + case Some(value) => ppnsConnector.updateCallBackUrl(clientId, boxId, value) + case None => Future.successful(PPNSCallBackUrlSuccessResponse) + } } yield result } diff --git a/app/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsService.scala b/app/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsService.scala index 3dab866..605ec8b 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsService.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsService.scala @@ -17,63 +17,63 @@ package uk.gov.hmrc.apisubscriptionfields.service import javax.inject._ -import uk.gov.hmrc.apisubscriptionfields.model._ -import Types._ - -import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.Future.successful +import scala.concurrent.{ExecutionContext, Future} + import cats.data.NonEmptyList -import uk.gov.hmrc.apisubscriptionfields.repository.SubscriptionFieldsRepository -import uk.gov.hmrc.http.HeaderCarrier import cats.data.{NonEmptyList => NEL} +import uk.gov.hmrc.http.HeaderCarrier + +import uk.gov.hmrc.apisubscriptionfields.model.Types._ +import uk.gov.hmrc.apisubscriptionfields.model._ +import uk.gov.hmrc.apisubscriptionfields.repository.SubscriptionFieldsRepository + @Singleton class SubscriptionFieldsService @Inject() ( - repository: SubscriptionFieldsRepository, - apiFieldDefinitionsService: ApiFieldDefinitionsService, - pushPullNotificationService: PushPullNotificationService)(implicit ec: ExecutionContext) { - + repository: SubscriptionFieldsRepository, + apiFieldDefinitionsService: ApiFieldDefinitionsService, + pushPullNotificationService: PushPullNotificationService +)(implicit ec: ExecutionContext) { private def validate(fields: Fields, fieldDefinitions: NonEmptyList[FieldDefinition]): SubsFieldValidationResponse = { - SubscriptionFieldsService.validateAgainstValidationRules(fieldDefinitions, fields) ++ SubscriptionFieldsService.validateFieldNamesAreDefined(fieldDefinitions,fields) match { + SubscriptionFieldsService.validateAgainstValidationRules(fieldDefinitions, fields) ++ SubscriptionFieldsService.validateFieldNamesAreDefined(fieldDefinitions, fields) match { case FieldErrorMap.empty => ValidSubsFieldValidationResponse case errs: FieldErrorMap => InvalidSubsFieldValidationResponse(errorResponses = errs) } } private def upsertSubscriptionFields(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, fields: Fields): Future[SuccessfulSubsFieldsUpsertResponse] = { - repository.saveAtomic(clientId, apiContext, apiVersion, fields) + repository + .saveAtomic(clientId, apiContext, apiVersion, fields) .map(result => SuccessfulSubsFieldsUpsertResponse(result._1, result._2)) } - def handlePPNS(clientId: ClientId, - apiContext: ApiContext, - apiVersion: ApiVersion, - fieldDefinitions: NEL[FieldDefinition], - fields: Fields)(implicit hc: HeaderCarrier): Future[SubsFieldsUpsertResponse] = { + def handlePPNS(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, fieldDefinitions: NEL[FieldDefinition], fields: Fields)(implicit + hc: HeaderCarrier + ): Future[SubsFieldsUpsertResponse] = { val ppnsFieldDefinition: Option[FieldDefinition] = fieldDefinitions.find(_.`type` == FieldDefinitionType.PPNS_FIELD) ppnsFieldDefinition match { case Some(fieldDefinition) => val oFieldValue: Option[FieldValue] = fields.get(fieldDefinition.name) pushPullNotificationService.subscribeToPPNS(clientId, apiContext, apiVersion, oFieldValue, fieldDefinition).flatMap { - case PPNSCallBackUrlSuccessResponse => upsertSubscriptionFields(clientId, apiContext, apiVersion, fields) + case PPNSCallBackUrlSuccessResponse => upsertSubscriptionFields(clientId, apiContext, apiVersion, fields) case PPNSCallBackUrlFailedResponse(error) => Future.successful(FailedValidationSubsFieldsUpsertResponse(Map(fieldDefinition.name -> error))) } - case None => upsertSubscriptionFields(clientId, apiContext, apiVersion, fields) + case None => upsertSubscriptionFields(clientId, apiContext, apiVersion, fields) } } - def upsert(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, fields: Fields) - (implicit hc: HeaderCarrier): Future[SubsFieldsUpsertResponse] = { + def upsert(clientId: ClientId, apiContext: ApiContext, apiVersion: ApiVersion, fields: Fields)(implicit hc: HeaderCarrier): Future[SubsFieldsUpsertResponse] = { val foFieldDefinitions: Future[Option[NonEmptyList[FieldDefinition]]] = apiFieldDefinitionsService.get(apiContext, apiVersion).map(_.map(_.fieldDefinitions)) get(clientId, apiContext, apiVersion).flatMap(_ match { case Some(sfields) if (sfields.fields == fields) => Future.successful(SuccessfulSubsFieldsUpsertResponse(sfields, false)) - case _ => - foFieldDefinitions.flatMap( _ match { + case _ => + foFieldDefinitions.flatMap(_ match { case None => successful(NotFoundSubsFieldsUpsertResponse) case Some(fieldDefinitions) => validate(fields, fieldDefinitions) match { @@ -108,17 +108,17 @@ class SubscriptionFieldsService @Inject() ( (for { fields <- repository.fetchByClientId(clientId) } yield fields) - .map { - case Nil => None - case fs => Some(BulkSubscriptionFieldsResponse(subscriptions = fs)) - } + .map { + case Nil => None + case fs => Some(BulkSubscriptionFieldsResponse(subscriptions = fs)) + } } def getAll: Future[BulkSubscriptionFieldsResponse] = { (for { fields <- repository.fetchAll } yield fields) - .map (BulkSubscriptionFieldsResponse(_)) + .map(BulkSubscriptionFieldsResponse(_)) } } @@ -133,19 +133,19 @@ object SubscriptionFieldsService { // Some is Some(error) def validateAgainstDefinition(fieldDefinition: FieldDefinition, value: FieldValue): Option[FieldError] = { - fieldDefinition.validation .flatMap(group => if (validateAgainstGroup(group, value)) None else Some((fieldDefinition.name, group.errorMessage))) + fieldDefinition.validation.flatMap(group => if (validateAgainstGroup(group, value)) None else Some((fieldDefinition.name, group.errorMessage))) } def validateAgainstValidationRules(fieldDefinitions: NonEmptyList[FieldDefinition], fields: Fields): FieldErrorMap = fieldDefinitions - .map(fd => validateAgainstDefinition(fd, fields.getOrElse(fd.name,""))) + .map(fd => validateAgainstDefinition(fd, fields.getOrElse(fd.name, ""))) .foldLeft(FieldErrorMap.empty) { - case (acc, None) => acc - case (acc, Some((name,msg))) => acc + (name -> msg) + case (acc, None) => acc + case (acc, Some((name, msg))) => acc + (name -> msg) } def validateFieldNamesAreDefined(fieldDefinitions: NonEmptyList[FieldDefinition], fields: Fields): FieldErrorMap = { val illegalNames = fields.keySet -- (fieldDefinitions.map(_.name).toList) - illegalNames.foldLeft(FieldErrorMap.empty)( (acc, name) => acc + (name -> "No Field Definition found for this Field")) + illegalNames.foldLeft(FieldErrorMap.empty)((acc, name) => acc + (name -> "No Field Definition found for this Field")) } -} \ No newline at end of file +} diff --git a/app/uk/gov/hmrc/apisubscriptionfields/utils/ApplicationLogger.scala b/app/uk/gov/hmrc/apisubscriptionfields/utils/ApplicationLogger.scala index 78fa4da..0a6d634 100644 --- a/app/uk/gov/hmrc/apisubscriptionfields/utils/ApplicationLogger.scala +++ b/app/uk/gov/hmrc/apisubscriptionfields/utils/ApplicationLogger.scala @@ -20,4 +20,4 @@ import play.api.Logger trait ApplicationLogger { protected val appLogger: Logger = Logger("application") -} +} diff --git a/build.sbt b/build.sbt index eb5c5cd..22b5aba 100644 --- a/build.sbt +++ b/build.sbt @@ -27,6 +27,16 @@ import scala.language.postfixOps val appName = "api-subscription-fields" +ThisBuild / scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.6.0" + +inThisBuild( + List( + scalaVersion := "2.12.15", + semanticdbEnabled := true, + semanticdbVersion := scalafixSemanticdb.revision + ) +) + resolvers ++= Seq( Resolver.sonatypeRepo("releases"), Resolver.sonatypeRepo("snapshots") @@ -45,6 +55,7 @@ lazy val microservice = Project(appName, file(".")) .settings(publishingSettings: _*) .settings(defaultSettings(): _*) .settings(acceptanceTestSettings: _*) + .settings(headerSettings(AcceptanceTest) ++ automateHeaderSettings(AcceptanceTest)) .settings(scalaVersion := "2.12.15") .settings(ScoverageSettings()) .settings( diff --git a/project/plugins.sbt b/project/plugins.sbt index f633872..52f3c1b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -9,4 +9,6 @@ addSbtPlugin("org.scoverage" %% "sbt-scoverage" % "2.0.0") addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0") addSbtPlugin("com.typesafe.play" %% "sbt-plugin" % "2.8.18") -addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.9") +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.9") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") +addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.2") diff --git a/scalastyle-config.xml b/scalastyle-config.xml index e48b66a..816918f 100644 --- a/scalastyle-config.xml +++ b/scalastyle-config.xml @@ -10,12 +10,7 @@ - - - - - - + diff --git a/test/uk/gov/hmrc/apisubscriptionfields/AsyncHmrcSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/AsyncHmrcSpec.scala index 3a6c46a..13d3427 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/AsyncHmrcSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/AsyncHmrcSpec.scala @@ -16,14 +16,12 @@ package uk.gov.hmrc.apisubscriptionfields -import org.mockito.{MockitoSugar, ArgumentMatchersSugar} +import org.mockito.{ArgumentMatchersSugar, MockitoSugar} import org.scalatest.{Matchers, OptionValues, WordSpec} import org.scalatestplus.play.WsScalaTestClient + import play.api.test.{DefaultAwaitTimeout, FutureAwaits} -abstract class HmrcSpec extends WordSpec with Matchers with OptionValues with WsScalaTestClient with MockitoSugar with ArgumentMatchersSugar { -} +abstract class HmrcSpec extends WordSpec with Matchers with OptionValues with WsScalaTestClient with MockitoSugar with ArgumentMatchersSugar {} -abstract class AsyncHmrcSpec - extends HmrcSpec with DefaultAwaitTimeout with FutureAwaits { -} +abstract class AsyncHmrcSpec extends HmrcSpec with DefaultAwaitTimeout with FutureAwaits {} diff --git a/test/uk/gov/hmrc/apisubscriptionfields/FieldDefinitionTestData.scala b/test/uk/gov/hmrc/apisubscriptionfields/FieldDefinitionTestData.scala index dea0226..fa61b2f 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/FieldDefinitionTestData.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/FieldDefinitionTestData.scala @@ -18,14 +18,15 @@ package uk.gov.hmrc.apisubscriptionfields import java.util.UUID -import uk.gov.hmrc.apisubscriptionfields.model._ -import Types._ import cats.data.NonEmptyList import eu.timepit.refined.api.Refined + import uk.gov.hmrc.apisubscriptionfields.model.DevhubAccessRequirement._ +import uk.gov.hmrc.apisubscriptionfields.model.Types._ +import uk.gov.hmrc.apisubscriptionfields.model._ trait FieldDefinitionTestData extends TestData { - import eu.timepit.refined.auto._ + import eu.timepit.refined.auto._ def fieldN(id: Int): FieldName = { val char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(id) @@ -33,8 +34,8 @@ trait FieldDefinitionTestData extends TestData { } final val AlphanumericFieldName: FieldName = "alphanumericField" - final val PasswordFieldName: FieldName = "password" - final val PPNSFieldFieldName: FieldName = "callbackurl" + final val PasswordFieldName: FieldName = "password" + final val PPNSFieldFieldName: FieldName = "callbackurl" final val FakeValidationRule: RegexValidationRule = RegexValidationRule(".*") @@ -42,25 +43,25 @@ trait FieldDefinitionTestData extends TestData { final val FakeUrlValidation: ValidationGroup = ValidationGroup("error message", NonEmptyList.one(UrlValidationRule)) - final val FakeFieldDefinitionUrl = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", Some(FakeUrlValidation)) - final val FakeFieldDefinitionUrlValidationEmpty = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", None) - final val FakeFieldDefinitionString = FieldDefinition(fieldN(2), "desc2", "hint2", FieldDefinitionType.STRING, "short description", Some(FakeValidation)) - final val FakeFieldDefinitionWithAccess: FieldDefinition = FakeFieldDefinitionString.copy(validation = None, access = AccessRequirements(devhub = DevhubAccessRequirements(read = AdminOnly))) - final val FakeFieldDefinitionSecureToken = FieldDefinition(fieldN(3), "desc3", "hint3", FieldDefinitionType.SECURE_TOKEN, "short description", Some(FakeValidation)) - final val NelOfFieldDefinitions = NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionUrl, FakeFieldDefinitionString, FakeFieldDefinitionSecureToken)) - final val FakeApiFieldDefinitions = ApiFieldDefinitions(FakeContext, FakeVersion, NelOfFieldDefinitions) - final val FakeApiFieldDefinitionsResponse = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitions.fieldDefinitions) - - final val AlphaNumericRegexRule: RegexValidationRule = RegexValidationRule("^[a-zA-Z0-9]+$") - final val PasswordRegexRule: RegexValidationRule = RegexValidationRule("^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$") - final val CallBackUrlRegexRule: RegexValidationRule = RegexValidationRule("^https.*") + final val FakeFieldDefinitionUrl = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", Some(FakeUrlValidation)) + final val FakeFieldDefinitionUrlValidationEmpty = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", None) + final val FakeFieldDefinitionString = FieldDefinition(fieldN(2), "desc2", "hint2", FieldDefinitionType.STRING, "short description", Some(FakeValidation)) + final val FakeFieldDefinitionWithAccess: FieldDefinition = + FakeFieldDefinitionString.copy(validation = None, access = AccessRequirements(devhub = DevhubAccessRequirements(read = AdminOnly))) + final val FakeFieldDefinitionSecureToken = FieldDefinition(fieldN(3), "desc3", "hint3", FieldDefinitionType.SECURE_TOKEN, "short description", Some(FakeValidation)) + final val NelOfFieldDefinitions = NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionUrl, FakeFieldDefinitionString, FakeFieldDefinitionSecureToken)) + final val FakeApiFieldDefinitions = ApiFieldDefinitions(FakeContext, FakeVersion, NelOfFieldDefinitions) + final val FakeApiFieldDefinitionsResponse = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitions.fieldDefinitions) + + final val AlphaNumericRegexRule: RegexValidationRule = RegexValidationRule("^[a-zA-Z0-9]+$") + final val PasswordRegexRule: RegexValidationRule = RegexValidationRule("^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$") + final val CallBackUrlRegexRule: RegexValidationRule = RegexValidationRule("^https.*") final val FakeValidationForAlphanumeric: ValidationGroup = ValidationGroup("Needs to be alpha numeric", NonEmptyList.one(AlphaNumericRegexRule)) - final val FakeValidationForPassword: ValidationGroup = + final val FakeValidationForPassword: ValidationGroup = ValidationGroup("Needs to be at least 8 chars with at least one lowercase, uppercase and special char", NonEmptyList.one(PasswordRegexRule)) - final val FakeValidationForPPNS: ValidationGroup = + final val FakeValidationForPPNS: ValidationGroup = ValidationGroup("CallBackUrl Validation", NonEmptyList.one(CallBackUrlRegexRule)) - final val FakeFieldDefinitionAlphnumericField = FieldDefinition( "alphanumericField", "an alphanumeric filed", @@ -69,20 +70,20 @@ trait FieldDefinitionTestData extends TestData { "an alphanumeric field", Some(FakeValidationForAlphanumeric) ) - final val FakeFieldDefinitionPassword = + final val FakeFieldDefinitionPassword = FieldDefinition("password", "password", "this is your password", FieldDefinitionType.SECURE_TOKEN, "password", Some(FakeValidationForPassword)) - final val FakeFieldDefinitionPPNSFields = + final val FakeFieldDefinitionPPNSFields = FieldDefinition("callbackurl", "callbackurl", "please enter a callback url", FieldDefinitionType.PPNS_FIELD, "callbackurl", Some(FakeValidationForPPNS)) - final val FakeApiFieldDefinitionssWithRegex = NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionAlphnumericField, FakeFieldDefinitionPassword)) - final val FakeApiFieldDefinitionsPPNSWithRegex = NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionAlphnumericField, FakeFieldDefinitionPassword, FakeFieldDefinitionPPNSFields)) + final val FakeApiFieldDefinitionssWithRegex = NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionAlphnumericField, FakeFieldDefinitionPassword)) + final val FakeApiFieldDefinitionsPPNSWithRegex = + NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionAlphnumericField, FakeFieldDefinitionPassword, FakeFieldDefinitionPPNSFields)) - final val FakeApiFieldDefinitionsWithRegex = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitionssWithRegex) + final val FakeApiFieldDefinitionsWithRegex = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitionssWithRegex) final val FakeApiFieldDefinitionsResponseWithRegex: ApiFieldDefinitions = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitionssWithRegex) final val FakeApiFieldDefinitionsResponsePPNSWithRegex: ApiFieldDefinitions = ApiFieldDefinitions(FakeContext, FakeVersion, FakeApiFieldDefinitionsPPNSWithRegex) - final val jsonInvalidRegexFieldsDefinitionRequest = """{ | "fieldDefinitions" : [ { @@ -116,8 +117,11 @@ trait FieldDefinitionTestData extends TestData { | } ] |}""".stripMargin - - def createApiFieldDefinitions(apiContext: ApiContext = FakeContext, apiVersion: ApiVersion = FakeVersion, fieldDefinitions: NonEmptyList[FieldDefinition] = NelOfFieldDefinitions) = + def createApiFieldDefinitions( + apiContext: ApiContext = FakeContext, + apiVersion: ApiVersion = FakeVersion, + fieldDefinitions: NonEmptyList[FieldDefinition] = NelOfFieldDefinitions + ) = ApiFieldDefinitions(apiContext, apiVersion, fieldDefinitions) def uniqueApiContext = ApiContext(UUID.randomUUID().toString) diff --git a/test/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldsTestData.scala b/test/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldsTestData.scala index 07de783..75a2c88 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldsTestData.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/SubscriptionFieldsTestData.scala @@ -17,49 +17,52 @@ package uk.gov.hmrc.apisubscriptionfields import java.util.UUID +import scala.concurrent.Future +import uk.gov.hmrc.apisubscriptionfields.model.Types._ import uk.gov.hmrc.apisubscriptionfields.model._ -import Types._ -import scala.concurrent.Future trait SubscriptionFieldsTestData extends FieldDefinitionTestData with ValidationRuleTestData { import eu.timepit.refined.auto._ final val FakeRawFieldsId = UUID.randomUUID() - final val FakeFieldsId = SubscriptionFieldsId(FakeRawFieldsId) + final val FakeFieldsId = SubscriptionFieldsId(FakeRawFieldsId) - final val EmptyResponse: Future[Option[SubscriptionFields]] = Future.successful(None) - final val FakeSubscriptionFields: Map[FieldName, String] = Map(fieldN(1) -> "X", fieldN(2) -> "Y") - final val SubscriptionFieldsMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123ab", PasswordFieldName -> "Qw12@ert") - final val SubscriptionFieldsNonMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123a", PasswordFieldName -> "Qw12@er") - final val SubscriptionFieldsMatchRegexValidationPPNS: Fields = Map(AlphanumericFieldName -> "ABC123abc", PasswordFieldName -> "Qw12@erty", PPNSFieldFieldName -> "https://www.mycallbackurl.com") + final val EmptyResponse: Future[Option[SubscriptionFields]] = Future.successful(None) + final val FakeSubscriptionFields: Map[FieldName, String] = Map(fieldN(1) -> "X", fieldN(2) -> "Y") + final val SubscriptionFieldsMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123ab", PasswordFieldName -> "Qw12@ert") + final val SubscriptionFieldsNonMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123a", PasswordFieldName -> "Qw12@er") + final val SubscriptionFieldsMatchRegexValidationPPNS: Fields = + Map(AlphanumericFieldName -> "ABC123abc", PasswordFieldName -> "Qw12@erty", PPNSFieldFieldName -> "https://www.mycallbackurl.com") final val SubscriptionFieldsDoNotMatchRegexValidationPPNS: Fields = Map(AlphanumericFieldName -> "ABC123abc", PasswordFieldName -> "Qw12@erty", PPNSFieldFieldName -> "foo") final val SubscriptionFieldsEmptyValueRegexValidationPPNS: Fields = Map(AlphanumericFieldName -> "ABC123abc", PasswordFieldName -> "Qw12@erty", PPNSFieldFieldName -> "") - final val SubscriptionFieldsDoNotMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123abc=", PasswordFieldName -> "Qw12erty") + final val SubscriptionFieldsDoNotMatchRegexValidation: Fields = Map(AlphanumericFieldName -> "ABC123abc=", PasswordFieldName -> "Qw12erty") - final val FakeApiSubscription = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, FakeSubscriptionFields) - final val FakeSubscriptionFieldsResponse: SubscriptionFields = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, FakeSubscriptionFields) + final val FakeApiSubscription = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, FakeSubscriptionFields) + final val FakeSubscriptionFieldsResponse: SubscriptionFields = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, FakeSubscriptionFields) final val FakeValidSubsFieldValidationResponse: SubsFieldValidationResponse = ValidSubsFieldValidationResponse - final val CallbackUrlFieldName: FieldName = "callbackUrl" + final val CallbackUrlFieldName: FieldName = "callbackUrl" final val FakeFieldErrorMessage1: FieldError = ((CallbackUrlFieldName, "Invalid Callback URL")) - final val EoriFieldName: FieldName = "EORI" - final val FakeFieldErrorMessage2 = ((EoriFieldName, "Invalid EORI")) - final val FakeFieldErrorMessages = Map( + final val EoriFieldName: FieldName = "EORI" + final val FakeFieldErrorMessage2 = ((EoriFieldName, "Invalid EORI")) + final val FakeFieldErrorMessages = Map( (CallbackUrlFieldName -> FakeFieldErrorMessage1._2), - (EoriFieldName -> FakeFieldErrorMessage2._2) + (EoriFieldName -> FakeFieldErrorMessage2._2) ) final val FakeInvalidSubsFieldValidationResponse: SubsFieldValidationResponse = InvalidSubsFieldValidationResponse(FakeFieldErrorMessages) final val FakeFieldErrorForAlphanumeric: FieldError = ((AlphanumericFieldName, "Needs to be alpha numeric")) - final val FakeFieldErrorForPassword = ((PasswordFieldName, "Needs to be at least 8 chars with at least one lowercase, uppercase and special char")) - final val FakeInvalidSubsFieldValidationResponse2 = InvalidSubsFieldValidationResponse(errorResponses = Map( - (AlphanumericFieldName -> FakeFieldErrorForAlphanumeric._2), - (PasswordFieldName -> FakeFieldErrorForPassword._2) - )) + final val FakeFieldErrorForPassword = ((PasswordFieldName, "Needs to be at least 8 chars with at least one lowercase, uppercase and special char")) + final val FakeInvalidSubsFieldValidationResponse2 = InvalidSubsFieldValidationResponse(errorResponses = + Map( + (AlphanumericFieldName -> FakeFieldErrorForAlphanumeric._2), + (PasswordFieldName -> FakeFieldErrorForPassword._2) + ) + ) - def subsFieldsFor(fields: Fields): SubscriptionFields = SubscriptionFields(FakeClientId,FakeContext, FakeVersion, FakeFieldsId, fields) + def subsFieldsFor(fields: Fields): SubscriptionFields = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, fields) // TODO sort this def createSubscriptionFieldsWithApiContext(clientId: ClientId = FakeClientId, rawContext: String = fakeRawContext) = { @@ -70,4 +73,4 @@ trait SubscriptionFieldsTestData extends FieldDefinitionTestData with Validation def uniqueClientId = ClientId(UUID.randomUUID().toString) } -object SubscriptionFieldsTestData extends SubscriptionFieldsTestData \ No newline at end of file +object SubscriptionFieldsTestData extends SubscriptionFieldsTestData diff --git a/test/uk/gov/hmrc/apisubscriptionfields/TestData.scala b/test/uk/gov/hmrc/apisubscriptionfields/TestData.scala index 9309eaf..fe31952 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/TestData.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/TestData.scala @@ -20,17 +20,18 @@ import java.util.UUID import play.api.http.HeaderNames.{ACCEPT, CONTENT_TYPE} import play.api.http.MimeTypes + import uk.gov.hmrc.apisubscriptionfields.model._ trait TestData { type EmulatedFailure = UnsupportedOperationException - final val emulatedFailure = new EmulatedFailure("Emulated failure.") - final val fakeRawClientId = UUID.randomUUID().toString + final val emulatedFailure = new EmulatedFailure("Emulated failure.") + final val fakeRawClientId = UUID.randomUUID().toString final val fakeRawClientId2 = UUID.randomUUID().toString - final val fakeRawContext = "acontext" - final val fakeRawContext2 = "acontext2" - final val fakeRawVersion = "1.0.2" + final val fakeRawContext = "acontext" + final val fakeRawContext2 = "acontext2" + final val fakeRawVersion = "1.0.2" final val FakeContext = ApiContext(fakeRawContext) @@ -44,7 +45,6 @@ trait TestData { } - object RequestHeaders { val CONTENT_TYPE_HEADER: (String, String) = CONTENT_TYPE -> MimeTypes.JSON diff --git a/test/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnectorSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnectorSpec.scala index 4c38491..a549a74 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnectorSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/connector/PushPullNotificationServiceConnectorSpec.scala @@ -19,27 +19,24 @@ package uk.gov.hmrc.apisubscriptionfields.connector import java.{util => ju} import akka.stream.Materializer -import org.scalatest.BeforeAndAfterEach -import org.scalatestplus.play.guice.GuiceOneAppPerSuite -import play.api.Application -import play.api.inject.guice.GuiceApplicationBuilder import com.github.tomakehurst.wiremock.WireMockServer +import com.github.tomakehurst.wiremock.client.WireMock import com.github.tomakehurst.wiremock.client.WireMock._ import com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig -import play.api.libs.json.Json -import play.api.http.Status.OK -import com.github.tomakehurst.wiremock.client.WireMock -import org.scalatest.BeforeAndAfterAll +import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach} +import org.scalatestplus.play.guice.GuiceOneAppPerSuite + +import play.api.Application import play.api.http.HeaderNames.{CONTENT_TYPE, USER_AGENT} -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec +import play.api.http.Status.OK +import play.api.inject.guice.GuiceApplicationBuilder +import play.api.libs.json.Json import uk.gov.hmrc.http.HeaderCarrier + +import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec import uk.gov.hmrc.apisubscriptionfields.model._ -class PushPullNotificationServiceConnectorSpec - extends AsyncHmrcSpec - with GuiceOneAppPerSuite - with JsonFormatters - with BeforeAndAfterAll with BeforeAndAfterEach { +class PushPullNotificationServiceConnectorSpec extends AsyncHmrcSpec with GuiceOneAppPerSuite with JsonFormatters with BeforeAndAfterAll with BeforeAndAfterEach { private val stubPort = 11111 private val stubHost = "localhost" @@ -70,35 +67,39 @@ class PushPullNotificationServiceConnectorSpec trait Setup { - val boxName = "box-name" - val clientId: ClientId = ClientId("client-id") + val boxName = "box-name" + val clientId: ClientId = ClientId("client-id") val subscriptionFieldsId: SubscriptionFieldsId = SubscriptionFieldsId(ju.UUID.randomUUID) - val boxId: BoxId = BoxId(ju.UUID.randomUUID()) + val boxId: BoxId = BoxId(ju.UUID.randomUUID()) val connector: PushPullNotificationServiceConnector = app.injector.instanceOf[PushPullNotificationServiceConnector] - def primeStub(path: String, requestBody: String, responseBody: String){ - wireMockServer.stubFor( - put(path).withRequestBody(equalTo(requestBody)) - .willReturn(aResponse() - .withHeader(CONTENT_TYPE, "application/json") - .withBody(responseBody) - .withStatus(OK))) + def primeStub(path: String, requestBody: String, responseBody: String) { + wireMockServer.stubFor( + put(path) + .withRequestBody(equalTo(requestBody)) + .willReturn( + aResponse() + .withHeader(CONTENT_TYPE, "application/json") + .withBody(responseBody) + .withStatus(OK) + ) + ) } - def verifyMock(path: String){ - wireMockServer.verify( + def verifyMock(path: String) { + wireMockServer.verify( putRequestedFor(urlPathEqualTo(path)) - .withHeader(CONTENT_TYPE, equalTo("application/json")) - .withHeader(USER_AGENT, equalTo("api-subscription-fields")) + .withHeader(CONTENT_TYPE, equalTo("application/json")) + .withHeader(USER_AGENT, equalTo("api-subscription-fields")) ) } - implicit val hc: HeaderCarrier = HeaderCarrier() + implicit val hc: HeaderCarrier = HeaderCarrier() } "PPNS Connector" should { "send proper request to post box" in new Setup { - val requestBody: String = Json.stringify(Json.toJson(CreateBoxRequest(boxName, clientId))) + val requestBody: String = Json.stringify(Json.toJson(CreateBoxRequest(boxName, clientId))) val responseBody: String = Json.stringify(Json.toJson(CreateBoxResponse(boxId))) val path = "/box" @@ -107,42 +108,40 @@ class PushPullNotificationServiceConnectorSpec val ret: BoxId = await(connector.ensureBoxIsCreated(boxName, clientId)) ret shouldBe boxId - verifyMock(path) + verifyMock(path) } "send proper request to subscribe" in new Setup { - val callbackUrl = "my-callback" - val requestBody: String = Json.stringify(Json.toJson(UpdateSubscriberRequest(SubscriberRequest(callbackUrl, "API_PUSH_SUBSCRIBER")))) + val callbackUrl = "my-callback" + val requestBody: String = Json.stringify(Json.toJson(UpdateSubscriberRequest(SubscriberRequest(callbackUrl, "API_PUSH_SUBSCRIBER")))) val responseBody: String = Json.stringify(Json.toJson(UpdateSubscriberResponse(boxId))) val path = s"/box/${boxId.value}/subscriber" - primeStub(path, requestBody, responseBody) + primeStub(path, requestBody, responseBody) val ret: Unit = await(connector.subscribe(boxId, callbackUrl)) ret shouldBe (()) verifyMock(path) } - - - "send proper request to update callback and map response on success" in new Setup { - val callbackUrl = "my-callback" - val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) + "send proper request to update callback and map response on success" in new Setup { + val callbackUrl = "my-callback" + val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) val responseBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlResponse(successful = true, None))) val path = s"/box/${boxId.value}/callback" - primeStub(path, requestBody, responseBody) + primeStub(path, requestBody, responseBody) val ret: PPNSCallBackUrlValidationResponse = await(connector.updateCallBackUrl(clientId, boxId, callbackUrl)) ret shouldBe PPNSCallBackUrlSuccessResponse - verifyMock(path) + verifyMock(path) } "send proper request to update callback (when callback is empty) and map response on success" in new Setup { - val callbackUrl = "" - val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) + val callbackUrl = "" + val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) val responseBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlResponse(successful = true, None))) val path = s"/box/${boxId.value}/callback" @@ -154,10 +153,9 @@ class PushPullNotificationServiceConnectorSpec verifyMock(path) } - - "send proper request to update callback and map response on failure" in new Setup { - val callbackUrl = "my-callback" - val requestBody: String = Json.stringify(Json.toJson( UpdateCallBackUrlRequest(clientId, callbackUrl))) + "send proper request to update callback and map response on failure" in new Setup { + val callbackUrl = "my-callback" + val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) val responseBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlResponse(successful = false, Some("some error")))) val path = s"/box/${boxId.value}/callback" @@ -166,12 +164,12 @@ class PushPullNotificationServiceConnectorSpec val ret: PPNSCallBackUrlValidationResponse = await(connector.updateCallBackUrl(clientId, boxId, callbackUrl)) ret shouldBe PPNSCallBackUrlFailedResponse("some error") - verifyMock(path) + verifyMock(path) } "send proper request to update callback and map response on failure with Unknown Error" in new Setup { - val callbackUrl = "my-callback" - val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) + val callbackUrl = "my-callback" + val requestBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlRequest(clientId, callbackUrl))) val responseBody: String = Json.stringify(Json.toJson(UpdateCallBackUrlResponse(successful = false, None))) val path = s"/box/${boxId.value}/callback" @@ -180,7 +178,7 @@ class PushPullNotificationServiceConnectorSpec val ret: PPNSCallBackUrlValidationResponse = await(connector.updateCallBackUrl(clientId, boxId, callbackUrl)) ret shouldBe PPNSCallBackUrlFailedResponse("Unknown Error") - verifyMock(path) + verifyMock(path) } } } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerDeleteSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerDeleteSpec.scala index dc46b96..905a837 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerDeleteSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerDeleteSpec.scala @@ -16,25 +16,21 @@ package uk.gov.hmrc.apisubscriptionfields.controller -import play.api.test.{FakeRequest, StubControllerComponentsFactory} -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData -import uk.gov.hmrc.apisubscriptionfields.model.JsonFormatters -import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec - import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future.successful + import play.api.libs.json._ import play.api.test.Helpers._ +import play.api.test.{FakeRequest, StubControllerComponentsFactory} + +import uk.gov.hmrc.apisubscriptionfields.model.JsonFormatters +import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData} -class ApiFieldDefinitionsControllerDeleteSpec - extends AsyncHmrcSpec - with FieldDefinitionTestData - with JsonFormatters - with StubControllerComponentsFactory { +class ApiFieldDefinitionsControllerDeleteSpec extends AsyncHmrcSpec with FieldDefinitionTestData with JsonFormatters with StubControllerComponentsFactory { private val mockFieldsDefinitionService = mock[ApiFieldDefinitionsService] - private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldsDefinitionService) + private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldsDefinitionService) "DELETE /definition/context/:apiContext/version/:apiVersion" should { "return NO_CONTENT (204) when successfully deleted from repo" in { diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerGetSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerGetSpec.scala index b517bb6..e05dd89 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerGetSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerGetSpec.scala @@ -16,25 +16,21 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future.{failed, successful} + import play.api.libs.json.{JsDefined, JsString, Json} -import play.api.test.{FakeRequest, StubControllerComponentsFactory} import play.api.test.Helpers._ -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData +import play.api.test.{FakeRequest, StubControllerComponentsFactory} + import uk.gov.hmrc.apisubscriptionfields.model.{ApiFieldDefinitions, BulkApiFieldDefinitionsResponse, JsonFormatters} import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec - -import scala.concurrent.Future.{successful,failed} -import scala.concurrent.ExecutionContext.Implicits.global +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData} -class ApiFieldDefinitionsControllerGetSpec - extends AsyncHmrcSpec - with FieldDefinitionTestData - with JsonFormatters - with StubControllerComponentsFactory { +class ApiFieldDefinitionsControllerGetSpec extends AsyncHmrcSpec with FieldDefinitionTestData with JsonFormatters with StubControllerComponentsFactory { private val mockFieldsDefinitionService = mock[ApiFieldDefinitionsService] - private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldsDefinitionService) + private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldsDefinitionService) private val responseJsonString = """{ @@ -72,8 +68,8 @@ class ApiFieldDefinitionsControllerGetSpec | } | ] |}""".stripMargin - private val responseJson = Json.parse(responseJsonString) - private val responseModel = responseJson.as[ApiFieldDefinitions] + private val responseJson = Json.parse(responseJsonString) + private val responseModel = responseJson.as[ApiFieldDefinitions] private val allResponseJsonString = """{ @@ -150,9 +146,9 @@ class ApiFieldDefinitionsControllerGetSpec | } | ] |}""".stripMargin - private val allResponseJson = Json.parse(allResponseJsonString) - private val allResponseModel = allResponseJson.as[BulkApiFieldDefinitionsResponse] - private val emptyAllResponseJson = Json.toJson(BulkApiFieldDefinitionsResponse(Seq())) + private val allResponseJson = Json.parse(allResponseJsonString) + private val allResponseModel = allResponseJson.as[BulkApiFieldDefinitionsResponse] + private val emptyAllResponseJson = Json.toJson(BulkApiFieldDefinitionsResponse(Seq())) "GET /definition/context/:apiContext/version/:apiVersion" should { "return OK when the expected record exists in the repo" in { diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPostSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPostSpec.scala index 92d7834..466f6cc 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPostSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPostSpec.scala @@ -16,25 +16,24 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future + +import cats.data.NonEmptyList + import play.api.libs.json.{JsValue, Json} import play.api.mvc._ import play.api.test.Helpers._ import play.api.test._ -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData + import uk.gov.hmrc.apisubscriptionfields.model.JsonFormatters import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec -import scala.concurrent.Future -import scala.concurrent.ExecutionContext.Implicits.global -import cats.data.NonEmptyList +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData} -class ApiFieldDefinitionsControllerPostSpec extends AsyncHmrcSpec - with FieldDefinitionTestData - with JsonFormatters - with StubControllerComponentsFactory { +class ApiFieldDefinitionsControllerPostSpec extends AsyncHmrcSpec with FieldDefinitionTestData with JsonFormatters with StubControllerComponentsFactory { private val mockFieldDefintionService = mock[ApiFieldDefinitionsService] - private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldDefintionService) + private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockFieldDefintionService) final val FakeValidRegexFieldsDefinitionRequest = FieldDefinitionsRequest(NonEmptyList.fromListUnsafe(List(FakeFieldDefinitionAlphnumericField, FakeFieldDefinitionPassword))) @@ -58,13 +57,14 @@ class ApiFieldDefinitionsControllerPostSpec extends AsyncHmrcSpec private def testSubmitResult(request: Request[JsValue])(test: Future[Result] => Unit) { val action: Action[JsValue] = controller.validateFieldsDefinition() - val result: Future[Result] = action.apply(request) + val result: Future[Result] = action.apply(request) test(result) } private def mkRequest(jsonBody: JsValue): Request[JsValue] = FakeRequest() - .withJsonBody(jsonBody).map(r => r.json) + .withJsonBody(jsonBody) + .map(r => r.json) private def mkJson(model: FieldDefinitionsRequest) = Json.toJson(model)(Json.writes[FieldDefinitionsRequest]) diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPutSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPutSpec.scala index ed52443..2f6e434 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPutSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/ApiFieldDefinitionsControllerPutSpec.scala @@ -16,26 +16,23 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future +import scala.concurrent.Future.successful + import play.api.libs.json.{JsValue, Json} import play.api.mvc._ import play.api.test.Helpers._ import play.api.test._ -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData + import uk.gov.hmrc.apisubscriptionfields.model.JsonFormatters import uk.gov.hmrc.apisubscriptionfields.service.ApiFieldDefinitionsService -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec - -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.Future.successful -import scala.concurrent.Future +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData} -class ApiFieldDefinitionsControllerPutSpec extends AsyncHmrcSpec - with FieldDefinitionTestData - with JsonFormatters - with StubControllerComponentsFactory { +class ApiFieldDefinitionsControllerPutSpec extends AsyncHmrcSpec with FieldDefinitionTestData with JsonFormatters with StubControllerComponentsFactory { private val mockApiFieldDefinitionsService = mock[ApiFieldDefinitionsService] - private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockApiFieldDefinitionsService) + private val controller = new ApiFieldDefinitionsController(stubControllerComponents(), mockApiFieldDefinitionsService) "PUT /definition/context/:apiContext/version/:apiVersion" should { "return CREATED when created in the repo" in { @@ -66,13 +63,14 @@ class ApiFieldDefinitionsControllerPutSpec extends AsyncHmrcSpec private def testSubmitResult(request: Request[JsValue])(test: Future[Result] => Unit) { val action: Action[JsValue] = controller.upsertFieldsDefinition(FakeContext, FakeVersion) - val result: Future[Result] = action.apply(request) + val result: Future[Result] = action.apply(request) test(result) } private def mkRequest(jsonBody: JsValue): Request[JsValue] = FakeRequest() - .withJsonBody(jsonBody).map(r => r.json) + .withJsonBody(jsonBody) + .map(r => r.json) private def mkJson(model: FieldDefinitionsRequest) = Json.toJson(model)(Json.writes[FieldDefinitionsRequest]) } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerGetSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerGetSpec.scala index 18c0f45..21fd07b 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerGetSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerGetSpec.scala @@ -16,24 +16,23 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future +import scala.concurrent.Future.{failed, successful} + import play.api.libs.json.{JsDefined, JsString, Json} import play.api.mvc._ import play.api.test.Helpers._ -import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData +import play.api.test.{FakeRequest, StubControllerComponentsFactory} + import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.service.SubscriptionFieldsService -import scala.concurrent.ExecutionContext.Implicits.global - -import scala.concurrent.Future -import scala.concurrent.Future.{successful,failed} -import play.api.test.StubControllerComponentsFactory -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec -import play.api.test.FakeRequest +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, SubscriptionFieldsTestData} class SubscriptionFieldsControllerGetSpec extends AsyncHmrcSpec with SubscriptionFieldsTestData with JsonFormatters with StubControllerComponentsFactory { private val mockSubscriptionFieldsService = mock[SubscriptionFieldsService] - private val controller = new SubscriptionFieldsController(stubControllerComponents(), mockSubscriptionFieldsService) + private val controller = new SubscriptionFieldsController(stubControllerComponents(), mockSubscriptionFieldsService) private val responseJsonString = """{ @@ -46,8 +45,8 @@ class SubscriptionFieldsControllerGetSpec extends AsyncHmrcSpec with Subscriptio | "token":"abc123" | } |}""".stripMargin - private val responseJson = Json.parse(responseJsonString) - private val responseModel = responseJson.as[SubscriptionFields] + private val responseJson = Json.parse(responseJsonString) + private val responseModel = responseJson.as[SubscriptionFields] private val bulkResponseJsonString = """{ @@ -75,8 +74,8 @@ class SubscriptionFieldsControllerGetSpec extends AsyncHmrcSpec with Subscriptio | ] |} |""".stripMargin - private val bulkResponseJson = Json.parse(bulkResponseJsonString) - private val bulkResponseModel = bulkResponseJson.as[BulkSubscriptionFieldsResponse] + private val bulkResponseJson = Json.parse(bulkResponseJsonString) + private val bulkResponseModel = bulkResponseJson.as[BulkSubscriptionFieldsResponse] "GET /field/application/{client-id}/context/{context}/version/{api-version}" should { diff --git a/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerPutSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerPutSpec.scala index fc3a94e..369655c 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerPutSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/controller/SubscriptionFieldsControllerPutSpec.scala @@ -16,29 +16,27 @@ package uk.gov.hmrc.apisubscriptionfields.controller +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future +import scala.concurrent.Future.successful + import akka.actor.ActorSystem -import play.api.libs.json.{Json, JsValue} + +import play.api.libs.json.{JsValue, Json} import play.api.mvc._ +import play.api.test.Helpers._ import play.api.test.{FakeRequest, StubControllerComponentsFactory} + import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.service.SubscriptionFieldsService import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, SubscriptionFieldsTestData} -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.Future -import scala.concurrent.Future.successful -import play.api.test.Helpers._ - -class SubscriptionFieldsControllerPutSpec - extends AsyncHmrcSpec - with SubscriptionFieldsTestData - with JsonFormatters - with StubControllerComponentsFactory { +class SubscriptionFieldsControllerPutSpec extends AsyncHmrcSpec with SubscriptionFieldsTestData with JsonFormatters with StubControllerComponentsFactory { private val mockSubscriptionFieldsService = mock[SubscriptionFieldsService] - private val controller = new SubscriptionFieldsController(stubControllerComponents(), mockSubscriptionFieldsService) - implicit private val actorSystem = ActorSystem("test") - + private val controller = new SubscriptionFieldsController(stubControllerComponents(), mockSubscriptionFieldsService) + implicit private val actorSystem = ActorSystem("test") + def subsFieldServiceUpsertReturns(response: SubsFieldsUpsertResponse) = { when(mockSubscriptionFieldsService.upsert(eqTo(FakeClientId), eqTo(FakeContext), eqTo(FakeVersion), eqTo(FakeSubscriptionFields))(*)).thenReturn(successful(response)) } @@ -94,13 +92,14 @@ class SubscriptionFieldsControllerPutSpec private def testSubmitResult(request: Request[JsValue])(test: Future[Result] => Unit) { val action: Action[JsValue] = controller.upsertSubscriptionFields(FakeClientId, FakeContext, FakeVersion) - val result: Future[Result] = action.apply(request) + val result: Future[Result] = action.apply(request) test(result) } private def mkRequest(jsonBody: JsValue): Request[JsValue] = FakeRequest() - .withJsonBody(jsonBody).map(r => r.json) + .withJsonBody(jsonBody) + .map(r => r.json) private def mkJson(model: SubscriptionFieldsRequest) = Json.toJson(model)(Json.writes[SubscriptionFieldsRequest]) } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirementsSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirementsSpec.scala index dcdc876..f4e02fc 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirementsSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/model/AccessRequirementsSpec.scala @@ -16,8 +16,8 @@ package uk.gov.hmrc.apisubscriptionfields.model -import org.scalatest.WordSpec -import org.scalatest.Matchers +import org.scalatest.{Matchers, WordSpec} + import uk.gov.hmrc.apisubscriptionfields.model.DevhubAccessLevel._ import uk.gov.hmrc.apisubscriptionfields.model.DevhubAccessRequirement._ diff --git a/test/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatterSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatterSpec.scala index 3dc29c3..46e61e5 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatterSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/model/JsonFormatterSpec.scala @@ -18,26 +18,27 @@ package uk.gov.hmrc.apisubscriptionfields.model import cats.data.NonEmptyList import org.scalatest.{Matchers, WordSpec} -import uk.gov.hmrc.apisubscriptionfields.{FieldDefinitionTestData, SubscriptionFieldsTestData} + import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType._ +import uk.gov.hmrc.apisubscriptionfields.{FieldDefinitionTestData, SubscriptionFieldsTestData} class JsonFormatterSpec extends WordSpec with Matchers with JsonFormatters with SubscriptionFieldsTestData with FieldDefinitionTestData { import play.api.libs.json._ - private val fakeFields = Map(fieldN(1) -> "v1") - private val subscriptionFields = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, fakeFields) + private val fakeFields = Map(fieldN(1) -> "v1") + private val subscriptionFields = SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, fakeFields) private val bulkSubscriptionFieldsResponse = BulkSubscriptionFieldsResponse(Seq(subscriptionFields)) - private val fakeApiFieldDefinitionsResponse = ApiFieldDefinitions(FakeContext, FakeVersion, NonEmptyList.one(FakeFieldDefinitionUrl)) + private val fakeApiFieldDefinitionsResponse = ApiFieldDefinitions(FakeContext, FakeVersion, NonEmptyList.one(FakeFieldDefinitionUrl)) private val fakeApiFieldDefinitionsResponseEmptyValidation = ApiFieldDefinitions(FakeContext, FakeVersion, NonEmptyList.one(FakeFieldDefinitionUrlValidationEmpty)) - private val bulkFieldsDefinitionResponse = BulkApiFieldDefinitionsResponse(Seq(fakeApiFieldDefinitionsResponse)) + private val bulkFieldsDefinitionResponse = BulkApiFieldDefinitionsResponse(Seq(fakeApiFieldDefinitionsResponse)) private def objectAsJsonString[A](a: A)(implicit t: Writes[A]) = Json.asciiStringify(Json.toJson(a)) - private val subscriptionFieldJson = + private val subscriptionFieldJson = s"""{"clientId":"$fakeRawClientId","apiContext":"$fakeRawContext","apiVersion":"$fakeRawVersion","fieldsId":"$FakeRawFieldsId","fields":{"fieldB":"v1"}}""" - private val fieldDefinitionJson = + private val fieldDefinitionJson = s"""{"apiContext":"$fakeRawContext","apiVersion":"$fakeRawVersion","fieldDefinitions":[{"name":"fieldB","description":"desc1","hint":"hint1","type":"URL","shortDescription":"short description","validation":{"errorMessage":"error message","rules":[{"UrlValidationRule":{}}]}}]}""" private val fieldDefinitionEmptyValidationJson = s"""{"apiContext":"$fakeRawContext","apiVersion":"$fakeRawVersion","fieldDefinitions":[{"name":"fieldB","description":"desc1","hint":"hint1","type":"URL","shortDescription":"short description"}]}""" @@ -174,7 +175,9 @@ class JsonFormatterSpec extends WordSpec with Matchers with JsonFormatters with } "unmarshall with non default correctly" in { - Json.fromJson[AccessRequirements](Json.parse("""{"devhub":{"read":"adminOnly"}}""")) shouldBe JsSuccess(AccessRequirements(devhub = DevhubAccessRequirements(read = AdminOnly))) + Json.fromJson[AccessRequirements](Json.parse("""{"devhub":{"read":"adminOnly"}}""")) shouldBe JsSuccess( + AccessRequirements(devhub = DevhubAccessRequirements(read = AdminOnly)) + ) } } @@ -184,8 +187,10 @@ class JsonFormatterSpec extends WordSpec with Matchers with JsonFormatters with } "marshal json without mention of default access" in { - objectAsJsonString(FakeFieldDefinitionWithAccess.copy(access = AccessRequirements.Default)) should not include(""""access":{"devhub":{"read":"adminOnly", "write":"adminOnly"}}""") - objectAsJsonString(FakeFieldDefinitionWithAccess.copy(access = AccessRequirements.Default)) should not include(""""access"""") + objectAsJsonString( + FakeFieldDefinitionWithAccess.copy(access = AccessRequirements.Default) + ) should not include (""""access":{"devhub":{"read":"adminOnly", "write":"adminOnly"}}""") + objectAsJsonString(FakeFieldDefinitionWithAccess.copy(access = AccessRequirements.Default)) should not include (""""access"""") } "unmarshal json string into a FieldDefinition" in { diff --git a/test/uk/gov/hmrc/apisubscriptionfields/model/ModelSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/model/ModelSpec.scala index 7b19b45..8a8327b 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/model/ModelSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/model/ModelSpec.scala @@ -16,11 +16,10 @@ package uk.gov.hmrc.apisubscriptionfields.model -import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData -import uk.gov.hmrc.apisubscriptionfields.HmrcSpec import org.scalatest.Matchers +import uk.gov.hmrc.apisubscriptionfields.{FieldDefinitionTestData, HmrcSpec, SubscriptionFieldsTestData} + class ModelSpec extends HmrcSpec with SubscriptionFieldsTestData with FieldDefinitionTestData with ValidationRuleTestData { "RegexValidationRule" should { "return true when the value is valid - correct case" in { @@ -56,13 +55,13 @@ class UrlValidationRuleSpec extends HmrcSpec with ValidationRuleTestData with Ma } "invalid urls" in { - invalidUrls.map(invalidUrl => { + invalidUrls.map(invalidUrl => { UrlValidationRule.validate(invalidUrl) shouldBe false }) } "handles internal mdtp domains in url" in { - UrlValidationRule.validate("https://who-cares.mdtp/pathy/mcpathface") shouldBe true + UrlValidationRule.validate("https://who-cares.mdtp/pathy/mcpathface") shouldBe true } } -} \ No newline at end of file +} diff --git a/test/uk/gov/hmrc/apisubscriptionfields/model/ValidationRuleTestData.scala b/test/uk/gov/hmrc/apisubscriptionfields/model/ValidationRuleTestData.scala index 3183e19..ae8b898 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/model/ValidationRuleTestData.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/model/ValidationRuleTestData.scala @@ -26,10 +26,10 @@ trait ValidationRuleTestData { val mixedCaseRule: ValidationRule = RegexValidationRule("""^[a-zA-Z]+$""") val atLeastThreeLongRule: ValidationRule = RegexValidationRule("""^.{3}.*$""") - val atLeastTenLongRule: ValidationRule = RegexValidationRule("""^.{10}.*$""") + val atLeastTenLongRule: ValidationRule = RegexValidationRule("""^.{10}.*$""") - val validUrl = "https://www.example.com/here/and/there" + val validUrl = "https://www.example.com/here/and/there" val localValidUrl = "https://localhost:9000/" - val invalidUrls = List("www.example.com", "ftp://example.com/abc", "https://www example.com", "https://www&example.com", "https://www,example.com") + val invalidUrls = List("www.example.com", "ftp://example.com/abc", "https://www example.com", "https://www&example.com", "https://www,example.com") } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/repository/ApiFieldDefinitionsRepositorySpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/repository/ApiFieldDefinitionsRepositorySpec.scala index 2853968..6b5e348 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/repository/ApiFieldDefinitionsRepositorySpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/repository/ApiFieldDefinitionsRepositorySpec.scala @@ -21,20 +21,21 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.{BeforeAndAfterEach, OptionValues} import org.scalatestplus.play.guice.GuiceOneAppPerSuite + import play.api.test.{DefaultAwaitTimeout, FutureAwaits} -import uk.gov.hmrc.apisubscriptionfields.model.{ApiContext, ApiFieldDefinitions} -import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData.{FakeContext, FakeVersion, NelOfFieldDefinitions, uniqueApiContext} import uk.gov.hmrc.mongo.play.json.Codecs -import scala.concurrent.ExecutionContext.Implicits.global +import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData.{FakeContext, FakeVersion, NelOfFieldDefinitions, uniqueApiContext} +import uk.gov.hmrc.apisubscriptionfields.model.{ApiContext, ApiFieldDefinitions} -class ApiFieldDefinitionsRepositorySpec extends AnyWordSpec - with GuiceOneAppPerSuite - with Matchers - with OptionValues - with DefaultAwaitTimeout - with FutureAwaits - with BeforeAndAfterEach { +class ApiFieldDefinitionsRepositorySpec + extends AnyWordSpec + with GuiceOneAppPerSuite + with Matchers + with OptionValues + with DefaultAwaitTimeout + with FutureAwaits + with BeforeAndAfterEach { private val repository = app.injector.instanceOf[ApiFieldDefinitionsMongoRepository] @@ -148,7 +149,6 @@ class ApiFieldDefinitionsRepositorySpec extends AnyWordSpec } private def selector(fd: ApiFieldDefinitions) = { - Filters.and(Filters.equal("apiContext", Codecs.toBson(fd.apiContext.value)), - Filters.equal("apiVersion", Codecs.toBson(fd.apiVersion.value))) + Filters.and(Filters.equal("apiContext", Codecs.toBson(fd.apiContext.value)), Filters.equal("apiVersion", Codecs.toBson(fd.apiVersion.value))) } } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/repository/MongoFormattersSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/repository/MongoFormattersSpec.scala index 22e998a..77dc422 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/repository/MongoFormattersSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/repository/MongoFormattersSpec.scala @@ -17,14 +17,16 @@ package uk.gov.hmrc.apisubscriptionfields.repository import cats.data.NonEmptyList + import play.api.libs.json.{JsSuccess, Json} -import uk.gov.hmrc.apisubscriptionfields.model.{FieldDefinition, FieldDefinitionType, JsonFormatters, RegexValidationRule, ValidationGroup} + import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec +import uk.gov.hmrc.apisubscriptionfields.model.{FieldDefinition, FieldDefinitionType, JsonFormatters, RegexValidationRule, ValidationGroup} class MongoFormattersSpec extends AsyncHmrcSpec with JsonFormatters { import eu.timepit.refined.auto._ - val validationRule = RegexValidationRule("test regex") + val validationRule = RegexValidationRule("test regex") final val validation = ValidationGroup("error message", NonEmptyList.one(validationRule)) "Field definition formatter" should { "Correctly unmarshall a JSON field definition with all the necessary fields" in { diff --git a/test/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepositorySpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepositorySpec.scala index c3b8a76..0069851 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepositorySpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/repository/SubscriptionFieldsRepositorySpec.scala @@ -17,28 +17,30 @@ package uk.gov.hmrc.apisubscriptionfields.repository import java.util.UUID -import org.scalatest.{BeforeAndAfterEach, OptionValues} -import uk.gov.hmrc.apisubscriptionfields.model._ -import Types._ +import scala.concurrent.Future + import org.mongodb.scala.model.Updates.set import org.mongodb.scala.model.{Filters, FindOneAndUpdateOptions, ReturnDocument} import org.scalatest.matchers.should.Matchers +import org.scalatest.{BeforeAndAfterEach, OptionValues} import org.scalatestplus.play.guice.GuiceOneAppPerSuite + import play.api.test.{DefaultAwaitTimeout, FutureAwaits} -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec -import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData.{FakeClientId, FakeClientId2, FakeContext, FakeContext2, FakeRawFieldsId, FakeVersion, createSubscriptionFieldsWithApiContext, fakeRawContext2, fieldN, uniqueClientId} import uk.gov.hmrc.mongo.play.json.Codecs -import scala.concurrent.ExecutionContext.Implicits.global -import scala.concurrent.Future +import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec +import uk.gov.hmrc.apisubscriptionfields.SubscriptionFieldsTestData._ +import uk.gov.hmrc.apisubscriptionfields.model.Types._ +import uk.gov.hmrc.apisubscriptionfields.model._ -class SubscriptionFieldsRepositorySpec extends AsyncHmrcSpec - with GuiceOneAppPerSuite - with Matchers - with OptionValues - with DefaultAwaitTimeout - with FutureAwaits - with BeforeAndAfterEach { +class SubscriptionFieldsRepositorySpec + extends AsyncHmrcSpec + with GuiceOneAppPerSuite + with Matchers + with OptionValues + with DefaultAwaitTimeout + with FutureAwaits + with BeforeAndAfterEach { val mockUuidCreator: UUIDCreator = new UUIDCreator { override def uuid(): UUID = FakeRawFieldsId @@ -61,17 +63,22 @@ class SubscriptionFieldsRepositorySpec extends AsyncHmrcSpec } private def selector(s: SubscriptionFields) = { - Filters.and(Filters.equal("apiContext", Codecs.toBson(s.apiContext.value)), + Filters.and( + Filters.equal("apiContext", Codecs.toBson(s.apiContext.value)), Filters.equal("apiVersion", Codecs.toBson(s.apiVersion.value)), - Filters.equal("clientId", Codecs.toBson(s.clientId.value))) + Filters.equal("clientId", Codecs.toBson(s.clientId.value)) + ) } def saveByFieldsId(subscription: SubscriptionFields): Future[SubscriptionFields] = { val query = Filters.equal("fieldsId", Codecs.toBson(subscription.fieldsId.value)) - repository.collection.findOneAndUpdate(filter = query, - update = set("fieldsId", Codecs.toBson(subscription.fieldsId.value)), - options = FindOneAndUpdateOptions().upsert(false).returnDocument(ReturnDocument.AFTER) - ).toFuture() + repository.collection + .findOneAndUpdate( + filter = query, + update = set("fieldsId", Codecs.toBson(subscription.fieldsId.value)), + options = FindOneAndUpdateOptions().upsert(false).returnDocument(ReturnDocument.AFTER) + ) + .toFuture() } def saveAtomic(subscriptionFields: SubscriptionFields) = @@ -107,7 +114,7 @@ class SubscriptionFieldsRepositorySpec extends AsyncHmrcSpec collectionSize shouldBe 1 val updatedSubscriptionFields = apiSubscriptionFields.copy(fields = Map(fieldN(4) -> "value_4")) - val resultAfterUpdate = await(saveAtomic(updatedSubscriptionFields)) + val resultAfterUpdate = await(saveAtomic(updatedSubscriptionFields)) validateResult(resultAfterUpdate, updatedSubscriptionFields, false) resultAfterCreate._1.fieldsId shouldBe resultAfterUpdate._1.fieldsId collectionSize shouldBe 1 @@ -149,7 +156,7 @@ class SubscriptionFieldsRepositorySpec extends AsyncHmrcSpec val result = await(repository.fetch(FakeClientId, FakeContext, FakeVersion)) result match { - case None => fail + case None => fail case Some(subscriptionFields: SubscriptionFields) => validateSubscriptionFields(subscriptionFields, apiSubscription) } } @@ -168,14 +175,14 @@ class SubscriptionFieldsRepositorySpec extends AsyncHmrcSpec "fetchByFieldsId" should { "retrieve the correct record from the `fieldsId` " in { - val apiSubscription = createApiSubscriptionFields() + val apiSubscription = createApiSubscriptionFields() val savedSubscriptionFields = await(saveAtomic(apiSubscription)) collectionSize shouldBe 1 val result = await(repository.fetchByFieldsId(savedSubscriptionFields._1.fieldsId)) result match { - case None => fail + case None => fail case Some(subscriptionFields: SubscriptionFields) => validateSubscriptionFields(subscriptionFields, apiSubscription) } } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsServiceSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsServiceSpec.scala index 92df74e..1574209 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsServiceSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/service/ApiFieldDefinitionsServiceSpec.scala @@ -16,19 +16,19 @@ package uk.gov.hmrc.apisubscriptionfields.service -import uk.gov.hmrc.apisubscriptionfields.FieldDefinitionTestData -import uk.gov.hmrc.apisubscriptionfields.model._ -import uk.gov.hmrc.apisubscriptionfields.repository.ApiFieldDefinitionsRepository -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future.{failed, successful} -import scala.concurrent.Future.{successful,failed} import cats.data.NonEmptyList -import scala.concurrent.ExecutionContext.Implicits.global + +import uk.gov.hmrc.apisubscriptionfields.model._ +import uk.gov.hmrc.apisubscriptionfields.repository.ApiFieldDefinitionsRepository +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData} class ApiFieldDefinitionsServiceSpec extends AsyncHmrcSpec with FieldDefinitionTestData { private val mockApiFieldDefinitionsRepository = mock[ApiFieldDefinitionsRepository] - private val service = new ApiFieldDefinitionsService(mockApiFieldDefinitionsRepository) + private val service = new ApiFieldDefinitionsService(mockApiFieldDefinitionsRepository) "getAll" should { "return an empty list when there are no records in the database collection" in { @@ -47,9 +47,12 @@ class ApiFieldDefinitionsServiceSpec extends AsyncHmrcSpec with FieldDefinitionT val result = await(service.getAll) - val expectedResponse = BulkApiFieldDefinitionsResponse(apis = Seq( - ApiFieldDefinitions(FakeContext, FakeVersion, NonEmptyList.one(FakeFieldDefinitionUrl)), - ApiFieldDefinitions(FakeContext2, FakeVersion, NonEmptyList.one(FakeFieldDefinitionString)))) + val expectedResponse = BulkApiFieldDefinitionsResponse(apis = + Seq( + ApiFieldDefinitions(FakeContext, FakeVersion, NonEmptyList.one(FakeFieldDefinitionUrl)), + ApiFieldDefinitions(FakeContext2, FakeVersion, NonEmptyList.one(FakeFieldDefinitionString)) + ) + ) result shouldBe expectedResponse } } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationServiceSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationServiceSpec.scala index 045e14b..2c093b9 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationServiceSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/service/PushPullNotificationServiceSpec.scala @@ -16,20 +16,21 @@ package uk.gov.hmrc.apisubscriptionfields.service -import java.{util=>ju} -import uk.gov.hmrc.apisubscriptionfields.model._ -import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType._ -import uk.gov.hmrc.apisubscriptionfields.{FieldDefinitionTestData, SubscriptionFieldsTestData} -import uk.gov.hmrc.apisubscriptionfields.AsyncHmrcSpec -import scala.concurrent.Future.{successful,failed} +import java.{util => ju} +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future.{failed, successful} + import uk.gov.hmrc.http.HeaderCarrier + import uk.gov.hmrc.apisubscriptionfields.connector.PushPullNotificationServiceConnector -import scala.concurrent.ExecutionContext.Implicits.global +import uk.gov.hmrc.apisubscriptionfields.model.FieldDefinitionType._ +import uk.gov.hmrc.apisubscriptionfields.model._ +import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData, SubscriptionFieldsTestData} class PushPullNotificationServiceSpec extends AsyncHmrcSpec with SubscriptionFieldsTestData with FieldDefinitionTestData { - val boxId: BoxId = BoxId(ju.UUID.randomUUID()) - val clientId: ClientId = ClientId(ju.UUID.randomUUID().toString) + val boxId: BoxId = BoxId(ju.UUID.randomUUID()) + val clientId: ClientId = ClientId(ju.UUID.randomUUID().toString) val apiContext: ApiContext = ApiContext("aContext") val apiVersion: ApiVersion = ApiVersion("aVersion") @@ -42,12 +43,11 @@ class PushPullNotificationServiceSpec extends AsyncHmrcSpec with SubscriptionFie } "subscribing to PPNS" should { - val ppnsFieldName = fieldN(1) - val callbackUrl = "123" - val oCallbackUrl = Some(callbackUrl) - val ppnsFieldDefinition = FieldDefinition(ppnsFieldName, "description-1", "hint-1", PPNS_FIELD, "short-description-1" ) - val expectedTopicName = s"${apiContext.value}##${apiVersion.value}##$ppnsFieldName" - + val ppnsFieldName = fieldN(1) + val callbackUrl = "123" + val oCallbackUrl = Some(callbackUrl) + val ppnsFieldDefinition = FieldDefinition(ppnsFieldName, "description-1", "hint-1", PPNS_FIELD, "short-description-1") + val expectedTopicName = s"${apiContext.value}##${apiVersion.value}##$ppnsFieldName" "succeed and return PPNSCallBackUrlSuccessResponse when update of callback URL is successful" in new Setup { when(mockPPNSConnector.ensureBoxIsCreated(eqTo(expectedTopicName), eqTo(clientId))(*)).thenReturn(successful(boxId)) @@ -63,7 +63,6 @@ class PushPullNotificationServiceSpec extends AsyncHmrcSpec with SubscriptionFie "succeed and return PPNSCallBackUrlSuccessResponse but not call updatecallBackUrl when field is empty" in new Setup { when(mockPPNSConnector.ensureBoxIsCreated(eqTo(expectedTopicName), eqTo(clientId))(*)).thenReturn(successful(boxId)) - val result: PPNSCallBackUrlValidationResponse = await(service.subscribeToPPNS(clientId, apiContext, apiVersion, None, ppnsFieldDefinition)) result shouldBe PPNSCallBackUrlSuccessResponse @@ -83,21 +82,21 @@ class PushPullNotificationServiceSpec extends AsyncHmrcSpec with SubscriptionFie verify(mockPPNSConnector).updateCallBackUrl(eqTo(clientId), eqTo(boxId), eqTo(callbackUrl))(*) } - "fail when box creation fails" in new Setup { - when(mockPPNSConnector.ensureBoxIsCreated(eqTo(expectedTopicName), eqTo(clientId))(*)).thenReturn(failed(new RuntimeException)) + "fail when box creation fails" in new Setup { + when(mockPPNSConnector.ensureBoxIsCreated(eqTo(expectedTopicName), eqTo(clientId))(*)).thenReturn(failed(new RuntimeException)) - intercept[RuntimeException] { - await(service.subscribeToPPNS(clientId, apiContext, apiVersion, oCallbackUrl, ppnsFieldDefinition)) - } - } + intercept[RuntimeException] { + await(service.subscribeToPPNS(clientId, apiContext, apiVersion, oCallbackUrl, ppnsFieldDefinition)) + } + } - "fail when update callback url fails" in new Setup { + "fail when update callback url fails" in new Setup { when(mockPPNSConnector.ensureBoxIsCreated(eqTo(expectedTopicName), eqTo(clientId))(*)).thenReturn(successful(boxId)) when(mockPPNSConnector.updateCallBackUrl(clientId, boxId, callbackUrl)(hc)).thenReturn(failed(new RuntimeException)) - intercept[RuntimeException] { - await(service.subscribeToPPNS(clientId, apiContext, apiVersion, oCallbackUrl, ppnsFieldDefinition)) - } - } + intercept[RuntimeException] { + await(service.subscribeToPPNS(clientId, apiContext, apiVersion, oCallbackUrl, ppnsFieldDefinition)) + } + } } } diff --git a/test/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsServiceSpec.scala b/test/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsServiceSpec.scala index d9518c3..858554a 100644 --- a/test/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsServiceSpec.scala +++ b/test/uk/gov/hmrc/apisubscriptionfields/service/SubscriptionFieldsServiceSpec.scala @@ -16,24 +16,24 @@ package uk.gov.hmrc.apisubscriptionfields.service -import java.{util => ju} +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future.{failed, successful} import cats.data.NonEmptyList + +import uk.gov.hmrc.http.HeaderCarrier + import uk.gov.hmrc.apisubscriptionfields.model.Types.FieldErrorMap import uk.gov.hmrc.apisubscriptionfields.model._ import uk.gov.hmrc.apisubscriptionfields.repository._ import uk.gov.hmrc.apisubscriptionfields.{AsyncHmrcSpec, FieldDefinitionTestData, SubscriptionFieldsTestData} -import uk.gov.hmrc.http.HeaderCarrier -import scala.concurrent.ExecutionContext.Implicits.global - -import scala.concurrent.Future.{failed, successful} class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionFieldsTestData with FieldDefinitionTestData { trait Setup { val mockSubscriptionFieldsRepository: SubscriptionFieldsMongoRepository = mock[SubscriptionFieldsMongoRepository] - val mockApiFieldDefinitionsService: ApiFieldDefinitionsService = mock[ApiFieldDefinitionsService] - val mockPushPullNotificationService: PushPullNotificationService = mock[PushPullNotificationService](org.mockito.Mockito.withSettings().verboseLogging()) + val mockApiFieldDefinitionsService: ApiFieldDefinitionsService = mock[ApiFieldDefinitionsService] + val mockPushPullNotificationService: PushPullNotificationService = mock[PushPullNotificationService](org.mockito.Mockito.withSettings().verboseLogging()) implicit val hc: HeaderCarrier = HeaderCarrier() @@ -122,12 +122,12 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField } "upsert" should { - val fieldsNonMatch: Types.Fields = SubscriptionFieldsNonMatchRegexValidation - val fields: Types.Fields = SubscriptionFieldsMatchRegexValidation + val fieldsNonMatch: Types.Fields = SubscriptionFieldsNonMatchRegexValidation + val fields: Types.Fields = SubscriptionFieldsMatchRegexValidation val subscriptionFieldsNonMatch: SubscriptionFields = subsFieldsFor(fieldsNonMatch) val subscriptionFieldsMatching: SubscriptionFields = subsFieldsFor(fields) - val ppnsSuccessResponse = successful(PPNSCallBackUrlSuccessResponse) - val ppnsFailureResponse = successful(PPNSCallBackUrlFailedResponse("An Error Occurred")) + val ppnsSuccessResponse = successful(PPNSCallBackUrlSuccessResponse) + val ppnsFailureResponse = successful(PPNSCallBackUrlFailedResponse("An Error Occurred")) "return false when updating an existing api subscription fields (no PPNS)" in new Setup { when(mockApiFieldDefinitionsService.get(FakeContext, FakeVersion)).thenReturn(successful(Some(FakeApiFieldDefinitionsResponseWithRegex))) @@ -158,12 +158,17 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField when(mockSubscriptionFieldsRepository.saveAtomic(*[ClientId], *[ApiContext], *[ApiVersion], *)).thenReturn(successful((subscriptionFieldsNonMatch, false))) when(mockSubscriptionFieldsRepository.fetch(FakeClientId, FakeContext, FakeVersion)).thenReturn(successful(Some((subscriptionFieldsNonMatch)))) - val result: SubsFieldsUpsertResponse = await(service.upsert(FakeClientId, FakeContext, FakeVersion, SubscriptionFieldsMatchRegexValidationPPNS)) result shouldBe SuccessfulSubsFieldsUpsertResponse(SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, fieldsNonMatch), isInsert = false) - verify(mockPushPullNotificationService).subscribeToPPNS(eqTo(FakeClientId), eqTo(FakeContext), eqTo(FakeVersion), eqTo(Some("https://www.mycallbackurl.com")), any[FieldDefinition])(any) + verify(mockPushPullNotificationService).subscribeToPPNS( + eqTo(FakeClientId), + eqTo(FakeContext), + eqTo(FakeVersion), + eqTo(Some("https://www.mycallbackurl.com")), + any[FieldDefinition] + )(any) verify(mockSubscriptionFieldsRepository).saveAtomic(*[ClientId], *[ApiContext], *[ApiVersion], *) } @@ -178,7 +183,7 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField result shouldBe SuccessfulSubsFieldsUpsertResponse(SubscriptionFields(FakeClientId, FakeContext, FakeVersion, FakeFieldsId, fieldsNonMatch), isInsert = false) - verify(mockPushPullNotificationService).subscribeToPPNS(eqTo(FakeClientId), eqTo(FakeContext), eqTo(FakeVersion),eqTo(Some("")), any[FieldDefinition])(any) + verify(mockPushPullNotificationService).subscribeToPPNS(eqTo(FakeClientId), eqTo(FakeContext), eqTo(FakeVersion), eqTo(Some("")), any[FieldDefinition])(any) verify(mockSubscriptionFieldsRepository).saveAtomic(*[ClientId], *[ApiContext], *[ApiVersion], *) } @@ -249,13 +254,13 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField "delete" should { "return true when the entry exists in the database collection" in new Setup { - when(mockSubscriptionFieldsRepository.delete(FakeClientId, FakeContext,FakeVersion)).thenReturn(successful(true)) + when(mockSubscriptionFieldsRepository.delete(FakeClientId, FakeContext, FakeVersion)).thenReturn(successful(true)) await(service.delete(FakeClientId, FakeContext, FakeVersion)) shouldBe true } "return false when the entry does not exist in the database collection" in new Setup { - when(mockSubscriptionFieldsRepository.delete(FakeClientId, FakeContext,FakeVersion)).thenReturn(successful(false)) + when(mockSubscriptionFieldsRepository.delete(FakeClientId, FakeContext, FakeVersion)).thenReturn(successful(false)) await(service.delete(FakeClientId, FakeContext, FakeVersion)) shouldBe false } @@ -273,7 +278,7 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField } } - def theErrorMessage(i: Int) = s"error message $i" + def theErrorMessage(i: Int) = s"error message $i" val validationGroup1: ValidationGroup = ValidationGroup(theErrorMessage(1), NonEmptyList(mixedCaseRule, List(atLeastThreeLongRule))) "validate value against group" should { @@ -282,7 +287,7 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField } "return false when the value is not mixed case or not at least 3 long" in new Setup { - val hasNumeralsValue = "A345" + val hasNumeralsValue = "A345" val veryShortMixedCase = "Ab" SubscriptionFieldsService.validateAgainstGroup(validationGroup1, hasNumeralsValue) shouldBe false SubscriptionFieldsService.validateAgainstGroup(validationGroup1, veryShortMixedCase) shouldBe false @@ -291,7 +296,7 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField "validate value against field defintion" should { val fieldDefintionWithoutValidation = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", None) - val fieldDefinitionWithValidation = fieldDefintionWithoutValidation.copy(validation = Some(validationGroup1)) + val fieldDefinitionWithValidation = fieldDefintionWithoutValidation.copy(validation = Some(validationGroup1)) "succeed when no validation is present on the field defintion" in new Setup { SubscriptionFieldsService.validateAgainstDefinition(fieldDefintionWithoutValidation, lowerCaseValue) shouldBe None @@ -306,7 +311,7 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField "validate Field Names Are Defined" should { val fieldDefinitionWithoutValidation = FieldDefinition(fieldN(1), "desc1", "hint1", FieldDefinitionType.URL, "short description", None) - val fields = Map(fieldN(1) -> "Emily") + val fields = Map(fieldN(1) -> "Emily") "succeed when Fields match Field Definitions" in new Setup { SubscriptionFieldsService.validateFieldNamesAreDefined(NonEmptyList.one(fieldDefinitionWithoutValidation), fields) shouldBe empty @@ -317,9 +322,9 @@ class SubscriptionFieldsServiceSpec extends AsyncHmrcSpec with SubscriptionField SubscriptionFieldsService.validateFieldNamesAreDefined(NonEmptyList.one(fieldDefinitionWithoutValidation), Map(fieldN(5) -> "Bob", fieldN(1) -> "Fred")) errs should not be empty errs.head match { - case (name, _) if name == fieldN(5)=> succeed - case _ => fail("Not the field we expected") + case (name, _) if name == fieldN(5) => succeed + case _ => fail("Not the field we expected") } } } -} \ No newline at end of file +}