From ad3a8d9a6d28640c8b559ed5ca29bab5c22ddf9d Mon Sep 17 00:00:00 2001 From: matthewharris1 <33547722+matthewharris1@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:01:22 +0100 Subject: [PATCH 1/5] DAC6-3209 | Scaffolded and amended new page + CYA validator --- .../SomeInformationMissingController.scala | 23 ++++ app/utils/CheckYourAnswersValidator.scala | 103 ++++++++++++++++++ .../SomeInformationMissingView.scala.html | 13 +++ conf/app.routes | 2 + conf/messages.en | 6 +- ...SomeInformationMissingControllerSpec.scala | 28 +++++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 app/controllers/SomeInformationMissingController.scala create mode 100644 app/utils/CheckYourAnswersValidator.scala create mode 100644 app/views/SomeInformationMissingView.scala.html create mode 100644 test/controllers/SomeInformationMissingControllerSpec.scala diff --git a/app/controllers/SomeInformationMissingController.scala b/app/controllers/SomeInformationMissingController.scala new file mode 100644 index 00000000..edf21a8c --- /dev/null +++ b/app/controllers/SomeInformationMissingController.scala @@ -0,0 +1,23 @@ +package controllers + +import controllers.actions._ +import javax.inject.Inject +import play.api.i18n.{I18nSupport, MessagesApi} +import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} +import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController +import views.html.SomeInformationMissingView + +class SomeInformationMissingController @Inject()( + override val messagesApi: MessagesApi, + identify: IdentifierAction, + getData: DataRetrievalAction, + requireData: DataRequiredAction, + val controllerComponents: MessagesControllerComponents, + view: SomeInformationMissingView + ) extends FrontendBaseController with I18nSupport { + + def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData) { + implicit request => + Ok(view()) + } +} diff --git a/app/utils/CheckYourAnswersValidator.scala b/app/utils/CheckYourAnswersValidator.scala new file mode 100644 index 00000000..00c53aac --- /dev/null +++ b/app/utils/CheckYourAnswersValidator.scala @@ -0,0 +1,103 @@ +/* + * Copyright 2024 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 utils + +import models.UserAnswers +import pages._ +import pages.addFinancialInstitution._ +import play.api.libs.json.Reads + +sealed trait AddFIValidator { + self: CheckYourAnswersValidator => + + private def firstContactPhoneMissingAnswers: Seq[Page] = (userAnswers.get(FirstContactHavePhonePage) match { + case Some(true) => checkPage(FirstContactPhoneNumberPage) + case Some(false) => None + case _ => Some(FirstContactPhoneNumberPage) + }).toSeq + + private def secContactPhoneMissingAnswers: Seq[Page] = (userAnswers.get(SecondContactCanWePhonePage) match { + case Some(true) => checkPage(SecondContactPhoneNumberPage) + case Some(false) => None + case _ => Some(SecondContactPhoneNumberPage) + }).toSeq + + private def checkFirstContactMissingAnswers: Seq[Page] = Seq( + checkPage(FirstContactNamePage), + checkPage(FirstContactEmailPage) + ).flatten ++ firstContactPhoneMissingAnswers + + private def checkChangeSecContactDetailsMissingAnswers: Seq[Page] = + userAnswers.get(SecondContactExistsPage) match { + case Some(true) => Seq( + checkPage(SecondContactNamePage), + checkPage(SecondContactEmailPage) + ).flatten ++ secContactPhoneMissingAnswers + case Some(false) => Seq.empty + case _ => Seq(SecondContactExistsPage) + } + + private[utils] def checkContactDetailsMissingAnswers = checkFirstContactMissingAnswers ++ checkChangeSecContactDetailsMissingAnswers + + private[utils] def checkAddressMissingAnswers: Seq[Page] = (userAnswers.get(WhereIsFIBasedPage) match { + case Some(true) => checkPage(PostcodePage) + .orElse( + any( + checkPage(SelectAddressPage), + checkPage(UkAddressPage) + ).map( + _ => PostcodePage + ) + ) + case Some(false) => checkPage(NonUkAddressPage) + case _ => Some(WhereIsFIBasedPage) + }).toSeq + + private def fiUTRMissingAnswers: Seq[Page] = (userAnswers.get(HaveUniqueTaxpayerReferencePage) match { + case Some(true) => checkPage(WhatIsUniqueTaxpayerReferencePage) + case Some(false) => None + case _ => Some(HaveUniqueTaxpayerReferencePage) + }).toSeq + + private def fiGIINMissingAnswers: Seq[Page] = (userAnswers.get(HaveGIINPage) match { + case Some(true) => checkPage(WhatIsGIINPage) + case Some(false) => None + case _ => Some(HaveGIINPage) + }).toSeq + + private[utils] def checkNameUTRGIINMissingAnswers: Seq[Page] = Seq( + checkPage(NameOfFinancialInstitutionPage) + ).flatten ++ fiUTRMissingAnswers ++ fiGIINMissingAnswers +} + +class CheckYourAnswersValidator(val userAnswers: UserAnswers) extends AddFIValidator { + + private[utils] def checkPage[A](page: QuestionPage[A])(implicit rds: Reads[A]): Option[Page] = + userAnswers.get(page) match { + case None => Some(page) + case _ => None + } + + private[utils] def any(checkPages: Option[Page]*): Option[Page] = checkPages.find(_.isEmpty).getOrElse(checkPages.last) + + def validate: Seq[Page] = checkNameUTRGIINMissingAnswers ++ checkAddressMissingAnswers ++ checkContactDetailsMissingAnswers + +} + +object CheckYourAnswersValidator { + def apply(userAnswers: UserAnswers): CheckYourAnswersValidator = new CheckYourAnswersValidator(userAnswers) +} diff --git a/app/views/SomeInformationMissingView.scala.html b/app/views/SomeInformationMissingView.scala.html new file mode 100644 index 00000000..9776ec09 --- /dev/null +++ b/app/views/SomeInformationMissingView.scala.html @@ -0,0 +1,13 @@ +@this( + layout: templates.Layout, + govukButton: GovukButton +) + +@()(implicit request: Request[_], messages: Messages) + +@layout(pageTitle = titleNoForm(messages("someInformationMissing.title"))) { + +

@messages("someInformationMissing.heading")

+ +

@messages("someInformationMissing.p1")

+} diff --git a/conf/app.routes b/conf/app.routes index 798d4352..fd00faa4 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -145,3 +145,5 @@ POST /registered-business/check-answers controllers GET /financial-institution-added controllers.addFinancialInstitution.FinancialInstitutionAddedConfirmationController.onPageLoad GET /your-fis controllers.YourFinancialInstitutionsController.onPageLoad + +GET /someInformationMissing controllers.SomeInformationMissingController.onPageLoad() diff --git a/conf/messages.en b/conf/messages.en index 146ffed1..9bbeb7d4 100644 --- a/conf/messages.en +++ b/conf/messages.en @@ -328,4 +328,8 @@ financialInstitutionAddedConfirmation.p2 = Back to manage your financial institu financialInstitutionAddedConfirmation.p3 = Back to manage your CRS and FATCA reports yourFinancialInstitutions.title = Your Financial Institutions (Please update as part of DAC6-3048) -yourFinancialInstitutions.heading = Your Financial Institutions (Please update as part of DAC6-3048) \ No newline at end of file +yourFinancialInstitutions.heading = Your Financial Institutions (Please update as part of DAC6-3048) + +someInformationMissing.title = Some information is missing +someInformationMissing.heading = Some information is missing +someInformationMissing.p1 = You must provide this information to update your financial institutions. diff --git a/test/controllers/SomeInformationMissingControllerSpec.scala b/test/controllers/SomeInformationMissingControllerSpec.scala new file mode 100644 index 00000000..e9bc095f --- /dev/null +++ b/test/controllers/SomeInformationMissingControllerSpec.scala @@ -0,0 +1,28 @@ +package controllers + +import base.SpecBase +import play.api.test.FakeRequest +import play.api.test.Helpers._ +import views.html.SomeInformationMissingView + +class SomeInformationMissingControllerSpec extends SpecBase { + + "SomeInformationMissing Controller" - { + + "must return OK and the correct view for a GET" in { + + val application = applicationBuilder(userAnswers = Some(emptyUserAnswers)).build() + + running(application) { + val request = FakeRequest(GET, routes.SomeInformationMissingController.onPageLoad().url) + + val result = route(application, request).value + + val view = application.injector.instanceOf[SomeInformationMissingView] + + status(result) mustEqual OK + contentAsString(result) mustEqual view()(request, messages(application)).toString + } + } + } +} From ad009ef0ae12c9cb23842d3ca2c998def601a309 Mon Sep 17 00:00:00 2001 From: matthewharris1 <33547722+matthewharris1@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:45:23 +0100 Subject: [PATCH 2/5] DAC6-3209 | Added generators for models/pages and a spec for CYAvalidation --- .../SomeInformationMissingController.scala | 34 ++- app/models/Name.scala | 1 + app/utils/CheckYourAnswersValidator.scala | 47 ++-- .../SomeInformationMissingView.scala.html | 16 ++ test-utils/generators/ModelGenerators.scala | 90 +++++++ test-utils/generators/PageGenerators.scala | 99 +++++++ .../UserAnswersEntryGenerators.scala | 106 ++++++++ .../generators/UserAnswersGenerator.scala | 252 ++++++++++++++++++ ...SomeInformationMissingControllerSpec.scala | 17 ++ .../utils/CheckYourAnswersValidatorSpec.scala | 87 ++++++ 10 files changed, 719 insertions(+), 30 deletions(-) create mode 100644 test-utils/generators/ModelGenerators.scala create mode 100644 test-utils/generators/PageGenerators.scala create mode 100644 test-utils/generators/UserAnswersEntryGenerators.scala create mode 100644 test-utils/generators/UserAnswersGenerator.scala create mode 100644 test/utils/CheckYourAnswersValidatorSpec.scala diff --git a/app/controllers/SomeInformationMissingController.scala b/app/controllers/SomeInformationMissingController.scala index edf21a8c..c9511dbb 100644 --- a/app/controllers/SomeInformationMissingController.scala +++ b/app/controllers/SomeInformationMissingController.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2024 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 controllers import controllers.actions._ @@ -7,17 +23,19 @@ import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController import views.html.SomeInformationMissingView -class SomeInformationMissingController @Inject()( - override val messagesApi: MessagesApi, - identify: IdentifierAction, - getData: DataRetrievalAction, - requireData: DataRequiredAction, - val controllerComponents: MessagesControllerComponents, - view: SomeInformationMissingView - ) extends FrontendBaseController with I18nSupport { +class SomeInformationMissingController @Inject() ( + override val messagesApi: MessagesApi, + identify: IdentifierAction, + getData: DataRetrievalAction, + requireData: DataRequiredAction, + val controllerComponents: MessagesControllerComponents, + view: SomeInformationMissingView +) extends FrontendBaseController + with I18nSupport { def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData) { implicit request => Ok(view()) } + } diff --git a/app/models/Name.scala b/app/models/Name.scala index 60dbbd84..484535d4 100644 --- a/app/models/Name.scala +++ b/app/models/Name.scala @@ -25,5 +25,6 @@ case class Name(firstName: String, lastName: String) { } object Name { + implicit val format: OFormat[Name] = Json.format[Name] } diff --git a/app/utils/CheckYourAnswersValidator.scala b/app/utils/CheckYourAnswersValidator.scala index 00c53aac..09c8115b 100644 --- a/app/utils/CheckYourAnswersValidator.scala +++ b/app/utils/CheckYourAnswersValidator.scala @@ -25,15 +25,15 @@ sealed trait AddFIValidator { self: CheckYourAnswersValidator => private def firstContactPhoneMissingAnswers: Seq[Page] = (userAnswers.get(FirstContactHavePhonePage) match { - case Some(true) => checkPage(FirstContactPhoneNumberPage) + case Some(true) => checkPage(FirstContactPhoneNumberPage) case Some(false) => None - case _ => Some(FirstContactPhoneNumberPage) + case _ => Some(FirstContactPhoneNumberPage) }).toSeq private def secContactPhoneMissingAnswers: Seq[Page] = (userAnswers.get(SecondContactCanWePhonePage) match { - case Some(true) => checkPage(SecondContactPhoneNumberPage) + case Some(true) => checkPage(SecondContactPhoneNumberPage) case Some(false) => None - case _ => Some(SecondContactPhoneNumberPage) + case _ => Some(SecondContactPhoneNumberPage) }).toSeq private def checkFirstContactMissingAnswers: Seq[Page] = Seq( @@ -43,45 +43,48 @@ sealed trait AddFIValidator { private def checkChangeSecContactDetailsMissingAnswers: Seq[Page] = userAnswers.get(SecondContactExistsPage) match { - case Some(true) => Seq( - checkPage(SecondContactNamePage), - checkPage(SecondContactEmailPage) - ).flatten ++ secContactPhoneMissingAnswers + case Some(true) => + Seq( + checkPage(SecondContactNamePage), + checkPage(SecondContactEmailPage) + ).flatten ++ secContactPhoneMissingAnswers case Some(false) => Seq.empty - case _ => Seq(SecondContactExistsPage) + case _ => Seq(SecondContactExistsPage) } private[utils] def checkContactDetailsMissingAnswers = checkFirstContactMissingAnswers ++ checkChangeSecContactDetailsMissingAnswers private[utils] def checkAddressMissingAnswers: Seq[Page] = (userAnswers.get(WhereIsFIBasedPage) match { - case Some(true) => checkPage(PostcodePage) - .orElse( - any( - checkPage(SelectAddressPage), - checkPage(UkAddressPage) - ).map( - _ => PostcodePage + case Some(true) => + checkPage(PostcodePage) + .orElse( + any( + checkPage(SelectAddressPage), + checkPage(UkAddressPage) + ).map( + _ => PostcodePage + ) ) - ) case Some(false) => checkPage(NonUkAddressPage) - case _ => Some(WhereIsFIBasedPage) + case _ => Some(WhereIsFIBasedPage) }).toSeq private def fiUTRMissingAnswers: Seq[Page] = (userAnswers.get(HaveUniqueTaxpayerReferencePage) match { - case Some(true) => checkPage(WhatIsUniqueTaxpayerReferencePage) + case Some(true) => checkPage(WhatIsUniqueTaxpayerReferencePage) case Some(false) => None - case _ => Some(HaveUniqueTaxpayerReferencePage) + case _ => Some(HaveUniqueTaxpayerReferencePage) }).toSeq private def fiGIINMissingAnswers: Seq[Page] = (userAnswers.get(HaveGIINPage) match { - case Some(true) => checkPage(WhatIsGIINPage) + case Some(true) => checkPage(WhatIsGIINPage) case Some(false) => None - case _ => Some(HaveGIINPage) + case _ => Some(HaveGIINPage) }).toSeq private[utils] def checkNameUTRGIINMissingAnswers: Seq[Page] = Seq( checkPage(NameOfFinancialInstitutionPage) ).flatten ++ fiUTRMissingAnswers ++ fiGIINMissingAnswers + } class CheckYourAnswersValidator(val userAnswers: UserAnswers) extends AddFIValidator { diff --git a/app/views/SomeInformationMissingView.scala.html b/app/views/SomeInformationMissingView.scala.html index 9776ec09..0a867b93 100644 --- a/app/views/SomeInformationMissingView.scala.html +++ b/app/views/SomeInformationMissingView.scala.html @@ -1,3 +1,19 @@ +@* + * Copyright 2024 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. + *@ + @this( layout: templates.Layout, govukButton: GovukButton diff --git a/test-utils/generators/ModelGenerators.scala b/test-utils/generators/ModelGenerators.scala new file mode 100644 index 00000000..a9bb3635 --- /dev/null +++ b/test-utils/generators/ModelGenerators.scala @@ -0,0 +1,90 @@ +/* + * 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 generators + +import models._ +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.{Arbitrary, Gen} +import utils.RegexConstants + +trait ModelGenerators extends RegexConstants with Generators { + + val maximumNumber = 999999 + val minimumNumber = 1 + val countryNumber = 2 + val EmailLength = 132 + val PhoneNumberLength = 24 + val MaxNameLength = 35 + + implicit lazy val arbitraryCountry: Arbitrary[Country] = + Arbitrary { + for { + state <- Gen.oneOf(Seq("Valid", "Invalid")) + code <- Gen.pick(countryNumber, 'A' to 'Z') + name <- arbitrary[String] + } yield Country(state, code.mkString, name) + } + + implicit lazy val arbitraryAddressWithoutId: Arbitrary[models.Address] = + Arbitrary { + for { + addressLine1 <- arbitrary[String].suchThat(_.nonEmpty) + addressLine2 <- arbitrary[Option[String]] + addressLine3 <- arbitrary[String].suchThat(_.nonEmpty) + addressLine4 <- arbitrary[Option[String]] + postCode <- arbitrary[Option[String]] + country <- arbitrary[Country] + } yield Address(addressLine1, addressLine2, addressLine3, addressLine4, postCode, country) + } + + implicit lazy val arbitraryAddressLookup: Arbitrary[models.AddressLookup] = + Arbitrary { + for { + addressLine1 <- arbitrary[Option[String]] + addressLine2 <- arbitrary[Option[String]] + addressLine3 <- arbitrary[Option[String]] + addressLine4 <- arbitrary[Option[String]] + postCode <- arbitrary[String] + town <- arbitrary[String] + county <- arbitrary[Option[String]] + } yield AddressLookup(addressLine1, addressLine2, addressLine3, addressLine4, town, county, postCode) + } + + implicit val arbitraryAddressResponse: Arbitrary[AddressResponse] = Arbitrary { + val postCode = for { + size <- Gen.chooseNum(5, 7) + postCode <- Gen.option(Gen.listOfN(size, Gen.alphaNumChar).map(_.mkString)) + } yield postCode + for { + addressline <- arbitrary[String] + addressline2 <- arbitrary[Option[String]] + addressline3 <- arbitrary[Option[String]] + addressline4 <- arbitrary[Option[String]] + postcode <- postCode + countrycode <- arbitrary[String] + } yield AddressResponse(addressline, addressline2, addressline3, addressline4, postcode, countrycode) + } + +//Line holder for template scripts + implicit val arbitraryUniqueTaxpayerReference: Arbitrary[UniqueTaxpayerReference] = Arbitrary { + for { + id <- arbitrary[String] + } yield UniqueTaxpayerReference(id) + } + + // Line holder for template scripts +} diff --git a/test-utils/generators/PageGenerators.scala b/test-utils/generators/PageGenerators.scala new file mode 100644 index 00000000..c5c4a200 --- /dev/null +++ b/test-utils/generators/PageGenerators.scala @@ -0,0 +1,99 @@ +/* + * 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 generators + +import org.scalacheck.Arbitrary + +trait PageGenerators { + + implicit lazy val arbitraryFetchedRegisteredAddressPage: Arbitrary[pages.addFinancialInstitution.IsRegisteredBusiness.FetchedRegisteredAddressPage.type] = + Arbitrary(pages.addFinancialInstitution.IsRegisteredBusiness.FetchedRegisteredAddressPage) + + implicit lazy val arbitraryIsTheAddressCorrectPage: Arbitrary[pages.addFinancialInstitution.IsRegisteredBusiness.IsTheAddressCorrectPage.type] = + Arbitrary(pages.addFinancialInstitution.IsRegisteredBusiness.IsTheAddressCorrectPage) + + implicit lazy val arbitraryIsThisYourBusinessNamePage: Arbitrary[pages.addFinancialInstitution.IsRegisteredBusiness.IsThisYourBusinessNamePage.type] = + Arbitrary(pages.addFinancialInstitution.IsRegisteredBusiness.IsThisYourBusinessNamePage) + + implicit lazy val arbitraryReportForRegisteredBusinessPage + : Arbitrary[pages.addFinancialInstitution.IsRegisteredBusiness.ReportForRegisteredBusinessPage.type] = + Arbitrary(pages.addFinancialInstitution.IsRegisteredBusiness.ReportForRegisteredBusinessPage) + + implicit lazy val arbitraryFirstContactEmailPage: Arbitrary[pages.addFinancialInstitution.FirstContactEmailPage.type] = + Arbitrary(pages.addFinancialInstitution.FirstContactEmailPage) + + implicit lazy val arbitraryFirstContactHavePhonePage: Arbitrary[pages.addFinancialInstitution.FirstContactHavePhonePage.type] = + Arbitrary(pages.addFinancialInstitution.FirstContactHavePhonePage) + + implicit lazy val arbitraryFirstContactNamePage: Arbitrary[pages.addFinancialInstitution.FirstContactNamePage.type] = + Arbitrary(pages.addFinancialInstitution.FirstContactNamePage) + + implicit lazy val arbitraryFirstContactPhoneNumberPage: Arbitrary[pages.addFinancialInstitution.FirstContactPhoneNumberPage.type] = + Arbitrary(pages.addFinancialInstitution.FirstContactPhoneNumberPage) + + implicit lazy val arbitraryHaveGIINPage: Arbitrary[pages.addFinancialInstitution.HaveGIINPage.type] = + Arbitrary(pages.addFinancialInstitution.HaveGIINPage) + + implicit lazy val arbitraryHaveUniqueTaxpayerReferencePage: Arbitrary[pages.addFinancialInstitution.HaveUniqueTaxpayerReferencePage.type] = + Arbitrary(pages.addFinancialInstitution.HaveUniqueTaxpayerReferencePage) + + implicit lazy val arbitraryIsThisAddressPage: Arbitrary[pages.addFinancialInstitution.IsThisAddressPage.type] = + Arbitrary(pages.addFinancialInstitution.IsThisAddressPage) + + implicit lazy val arbitraryNameOfFinancialInstitutionPage: Arbitrary[pages.addFinancialInstitution.NameOfFinancialInstitutionPage.type] = + Arbitrary(pages.addFinancialInstitution.NameOfFinancialInstitutionPage) + + implicit lazy val arbitraryNonUkAddressPage: Arbitrary[pages.addFinancialInstitution.NonUkAddressPage.type] = + Arbitrary(pages.addFinancialInstitution.NonUkAddressPage) + + implicit lazy val arbitraryPostcodePage: Arbitrary[pages.addFinancialInstitution.PostcodePage.type] = + Arbitrary(pages.addFinancialInstitution.PostcodePage) + + implicit lazy val arbitrarySecondContactCanWePhonePage: Arbitrary[pages.addFinancialInstitution.SecondContactCanWePhonePage.type] = + Arbitrary(pages.addFinancialInstitution.SecondContactCanWePhonePage) + + implicit lazy val arbitrarySecondContactEmailPage: Arbitrary[pages.addFinancialInstitution.SecondContactEmailPage.type] = + Arbitrary(pages.addFinancialInstitution.SecondContactEmailPage) + + implicit lazy val arbitrarySecondContactExistsPage: Arbitrary[pages.addFinancialInstitution.SecondContactExistsPage.type] = + Arbitrary(pages.addFinancialInstitution.SecondContactExistsPage) + + implicit lazy val arbitrarySecondContactNamePage: Arbitrary[pages.addFinancialInstitution.SecondContactNamePage.type] = + Arbitrary(pages.addFinancialInstitution.SecondContactNamePage) + + implicit lazy val arbitrarySecondContactPhoneNumberPage: Arbitrary[pages.addFinancialInstitution.SecondContactPhoneNumberPage.type] = + Arbitrary(pages.addFinancialInstitution.SecondContactPhoneNumberPage) + + implicit lazy val arbitrarySelectAddressPage: Arbitrary[pages.addFinancialInstitution.SelectAddressPage.type] = + Arbitrary(pages.addFinancialInstitution.SelectAddressPage) + + implicit lazy val arbitrarySelectedAddressLookupPage: Arbitrary[pages.addFinancialInstitution.SelectedAddressLookupPage.type] = + Arbitrary(pages.addFinancialInstitution.SelectedAddressLookupPage) + + implicit lazy val arbitraryUkAddressPage: Arbitrary[pages.addFinancialInstitution.UkAddressPage.type] = + Arbitrary(pages.addFinancialInstitution.UkAddressPage) + + implicit lazy val arbitraryWhatIsGIINPage: Arbitrary[pages.addFinancialInstitution.WhatIsGIINPage.type] = + Arbitrary(pages.addFinancialInstitution.WhatIsGIINPage) + + implicit lazy val arbitraryWhatIsUniqueTaxpayerReferencePage: Arbitrary[pages.addFinancialInstitution.WhatIsUniqueTaxpayerReferencePage.type] = + Arbitrary(pages.addFinancialInstitution.WhatIsUniqueTaxpayerReferencePage) + + implicit lazy val arbitraryWhereIsFIBasedPage: Arbitrary[pages.addFinancialInstitution.WhereIsFIBasedPage.type] = + Arbitrary(pages.addFinancialInstitution.WhereIsFIBasedPage) + +} diff --git a/test-utils/generators/UserAnswersEntryGenerators.scala b/test-utils/generators/UserAnswersEntryGenerators.scala new file mode 100644 index 00000000..f0443a28 --- /dev/null +++ b/test-utils/generators/UserAnswersEntryGenerators.scala @@ -0,0 +1,106 @@ +/* + * 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 generators + +import org.scalacheck.{Arbitrary, Gen} +import play.api.libs.json.{JsValue, Json, Writes} + +trait UserAnswersEntryGenerators extends PageGenerators with ModelGenerators { + + implicit lazy val arbitraryFirstContactEmailUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.FirstContactEmailPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.FirstContactEmailPage) + + implicit lazy val arbitraryFirstContactHavePhoneUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.FirstContactHavePhonePage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.FirstContactHavePhonePage.type, Boolean](pages.addFinancialInstitution.FirstContactHavePhonePage) + + implicit lazy val arbitraryFirstContactPhoneNumberUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.FirstContactPhoneNumberPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.FirstContactPhoneNumberPage) + + implicit lazy val arbitraryFirstContactNameUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.FirstContactNamePage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.FirstContactNamePage) + + implicit lazy val arbitraryHaveGIINPageUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.HaveGIINPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.HaveGIINPage.type, Boolean](pages.addFinancialInstitution.HaveGIINPage) + + implicit lazy val arbitraryHaveUniqueTaxPayerReferenceUserAnswersEntry + : Arbitrary[(pages.addFinancialInstitution.HaveUniqueTaxpayerReferencePage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.HaveUniqueTaxpayerReferencePage.type, Boolean](pages.addFinancialInstitution.HaveUniqueTaxpayerReferencePage) + + implicit lazy val arbitraryIsThisAddressUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.IsThisAddressPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.IsThisAddressPage.type, Boolean](pages.addFinancialInstitution.IsThisAddressPage) + + implicit lazy val arbitraryNameOfFinancialInstitutionUserAnswersEntry + : Arbitrary[(pages.addFinancialInstitution.NameOfFinancialInstitutionPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.NameOfFinancialInstitutionPage) + + implicit lazy val arbitraryNonUkAddressPageEntry: Arbitrary[(pages.addFinancialInstitution.NonUkAddressPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.NonUkAddressPage.type, models.Address](pages.addFinancialInstitution.NonUkAddressPage) + + implicit lazy val arbitraryPostcodePageUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.PostcodePage.type, JsValue)] = + alphaStrPageArbitrary(pages.addFinancialInstitution.PostcodePage) + + implicit lazy val arbitrarySecondContactCanWePhoneUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SecondContactCanWePhonePage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.SecondContactCanWePhonePage.type, Boolean](pages.addFinancialInstitution.SecondContactCanWePhonePage) + + implicit lazy val arbitrarySecondContactEmailUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SecondContactEmailPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.SecondContactEmailPage) + + implicit lazy val arbitrarySecondContactExistsUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SecondContactExistsPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.SecondContactExistsPage.type, Boolean](pages.addFinancialInstitution.SecondContactExistsPage) + + implicit lazy val arbitrarySecondContactNameUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SecondContactNamePage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.SecondContactNamePage) + + implicit lazy val arbitrarySecondContactPhoneNumberUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SecondContactPhoneNumberPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.SecondContactPhoneNumberPage) + + implicit lazy val arbitrarySelectAddressUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.SelectAddressPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.SelectAddressPage) + + implicit lazy val arbitraryUkAddressEntry: Arbitrary[(pages.addFinancialInstitution.UkAddressPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.UkAddressPage.type, models.Address](pages.addFinancialInstitution.UkAddressPage) + + implicit lazy val arbitraryWhatIsGIINUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.WhatIsGIINPage.type, JsValue)] = + alphaStrNonEmptyPageArbitrary(pages.addFinancialInstitution.WhatIsGIINPage) + + implicit lazy val arbitraryWhatIsUniqueTaxpayerReferenceEntry: Arbitrary[(pages.addFinancialInstitution.WhatIsUniqueTaxpayerReferencePage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.WhatIsUniqueTaxpayerReferencePage.type, models.UniqueTaxpayerReference]( + pages.addFinancialInstitution.WhatIsUniqueTaxpayerReferencePage + ) + + implicit lazy val arbitraryWhereIsFIBasedUserAnswersEntry: Arbitrary[(pages.addFinancialInstitution.WhereIsFIBasedPage.type, JsValue)] = + modelArbitrary[pages.addFinancialInstitution.WhereIsFIBasedPage.type, Boolean](pages.addFinancialInstitution.WhereIsFIBasedPage) + + private def alphaStrNonEmptyPageArbitrary[T](page: T): Arbitrary[(T, JsValue)] = Arbitrary { + for { + value <- Gen.alphaStr.suchThat(_.nonEmpty).map(Json.toJson(_)) + } yield (page, value) + } + + private def alphaStrPageArbitrary[T](page: T): Arbitrary[(T, JsValue)] = Arbitrary { + for { + value <- Gen.alphaStr.map(Json.toJson(_)) + } yield (page, value) + } + + private def modelArbitrary[T, U](page: T)(implicit arb: Arbitrary[U], writes: Writes[U]): Arbitrary[(T, JsValue)] = Arbitrary { + for { + value <- arb.arbitrary.map(Json.toJson(_)) + } yield (page, value) + } + +} diff --git a/test-utils/generators/UserAnswersGenerator.scala b/test-utils/generators/UserAnswersGenerator.scala new file mode 100644 index 00000000..6c65434d --- /dev/null +++ b/test-utils/generators/UserAnswersGenerator.scala @@ -0,0 +1,252 @@ +/* + * 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 generators + +import models.{RichJsObject, UserAnswers} +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.{Arbitrary, Gen} +import org.scalatest.TryValues +import pages._ +import pages.addFinancialInstitution._ +import play.api.libs.json.{JsObject, JsPath, JsValue, Json} + +trait UserAnswersGenerator extends UserAnswersEntryGenerators with TryValues { + self: Generators => + + val generators: Seq[Gen[(QuestionPage[_], JsValue)]] = + arbitrary[(FirstContactEmailPage.type, JsValue)] :: + arbitrary[(FirstContactHavePhonePage.type, JsValue)] :: + arbitrary[(FirstContactNamePage.type, JsValue)] :: + arbitrary[(FirstContactPhoneNumberPage.type, JsValue)] :: + arbitrary[(HaveGIINPage.type, JsValue)] :: + arbitrary[(HaveUniqueTaxpayerReferencePage.type, JsValue)] :: + arbitrary[(IsThisAddressPage.type, JsValue)] :: + arbitrary[(NameOfFinancialInstitutionPage.type, JsValue)] :: + arbitrary[(NonUkAddressPage.type, JsValue)] :: + arbitrary[(PostcodePage.type, JsValue)] :: + arbitrary[(SecondContactCanWePhonePage.type, JsValue)] :: + arbitrary[(SecondContactEmailPage.type, JsValue)] :: + arbitrary[(SecondContactExistsPage.type, JsValue)] :: + arbitrary[(SecondContactNamePage.type, JsValue)] :: + arbitrary[(SecondContactPhoneNumberPage.type, JsValue)] :: + arbitrary[(SelectAddressPage.type, JsValue)] :: + arbitrary[(UkAddressPage.type, JsValue)] :: + arbitrary[(WhatIsGIINPage.type, JsValue)] :: + arbitrary[(WhatIsUniqueTaxpayerReferencePage.type, JsValue)] :: + arbitrary[(WhereIsFIBasedPage.type, JsValue)] :: + Nil + + implicit lazy val arbitraryUserData: Arbitrary[UserAnswers] = Arbitrary { + for { + id <- nonEmptyString + data <- generators match { + case Nil => Gen.const(Map[QuestionPage[_], JsValue]()) + case _ => Gen.mapOf(oneOf(generators)) + } + } yield UserAnswers( + id = id, + data = data.foldLeft(Json.obj()) { + case (obj, (path, value)) => + obj.setObject(path.path, value).get + } + ) + } + + private def genJsObj(gens: Gen[(QuestionPage[_], JsValue)]*): Gen[JsObject] = + Gen.sequence[Seq[(QuestionPage[_], JsValue)], (QuestionPage[_], JsValue)](gens).map { + seq => + seq.foldLeft(Json.obj()) { + case (obj, (page, value)) => + obj.setObject(page.path, value).get + } + } + + private def setFields(obj: JsObject, fields: (JsPath, JsValue)*): JsObject = + fields.foldLeft(obj) { + case (acc, (path, value)) => acc.setObject(path, value).get + } + + private lazy val ukAddress = + Arbitrary { + for { + postCode <- genJsObj(arbitrary[(PostcodePage.type, JsValue)]) + isThisYourAddress <- arbitrary[Boolean] + data <- + if (isThisYourAddress) { + genJsObj(arbitrary[(SelectAddressPage.type, JsValue)]) + } else { + genJsObj(arbitrary[(UkAddressPage.type, JsValue)]) + } + } yield postCode ++ data + } + + private lazy val address = + Arbitrary { + for { + whereDoYouLive <- arbitrary[Boolean] + data <- + if (whereDoYouLive) { + ukAddress.arbitrary + } else { + genJsObj(arbitrary[(NonUkAddressPage.type, JsValue)]) + } + obj = setFields( + Json.obj(), + WhereIsFIBasedPage.path -> Json.toJson(whereDoYouLive) + ) ++ data + } yield obj + } + + private def phoneNumberArbitrary[T <: QuestionPage[Boolean], U <: QuestionPage[String]]( + havePhonePage: T, + phonePage: U + )(implicit arb: Arbitrary[(phonePage.type, JsValue)]) = Arbitrary { + for { + havePhone <- arbitrary[Boolean] + data <- + if (havePhone) { + genJsObj(arbitrary[(phonePage.type, JsValue)]) + } else { + Gen.const(Json.obj()) + } + obj = setFields( + Json.obj(), + havePhonePage.path -> Json.toJson(havePhone) + ) ++ data + } yield obj + } + + private def pageArbitrary[T <: QuestionPage[_]](page: T)(implicit arb: Arbitrary[(page.type, JsValue)]) = Arbitrary { + for { + email <- genJsObj(arbitrary[(page.type, JsValue)]) + } yield email + } + + private lazy val firstContactDetails = Arbitrary { + for { + name <- genJsObj(arbitrary[(FirstContactNamePage.type, JsValue)]) + email <- genJsObj(arbitrary[(FirstContactEmailPage.type, JsValue)]) + phone <- phoneNumberArbitrary(FirstContactHavePhonePage, FirstContactPhoneNumberPage).arbitrary + } yield name ++ email ++ phone + } + + private lazy val secondContactDetails = Arbitrary { + for { + name <- genJsObj(arbitrary[(SecondContactNamePage.type, JsValue)]) + email <- genJsObj(arbitrary[(SecondContactEmailPage.type, JsValue)]) + phone <- phoneNumberArbitrary(SecondContactCanWePhonePage, SecondContactPhoneNumberPage).arbitrary + } yield name ++ email ++ phone + } + + private lazy val firstAndSecondContactDetails = Arbitrary { + for { + haveSecondContact <- arbitrary[Boolean] + firstContact <- firstContactDetails.arbitrary + secondContact <- + if (haveSecondContact) { + secondContactDetails.arbitrary + } else { + Gen.const(Json.obj()) + } + obj = setFields( + Json.obj(), + SecondContactExistsPage.path -> Json.toJson(haveSecondContact) + ) ++ firstContact ++ secondContact + } yield obj + } + + private lazy val nameUTRandGIINDetails = Arbitrary { + for { + haveUTR <- arbitrary[Boolean] + haveGIIN <- arbitrary[Boolean] + fiName <- + pageArbitrary(NameOfFinancialInstitutionPage).arbitrary + utr <- + if (haveUTR) { + pageArbitrary(WhatIsUniqueTaxpayerReferencePage).arbitrary + } else { + Gen.const(Json.obj()) + } + giin <- + if (haveGIIN) { + pageArbitrary(WhatIsGIINPage).arbitrary + } else { + Gen.const(Json.obj()) + } + obj = setFields( + Json.obj(), + HaveUniqueTaxpayerReferencePage.path -> Json.toJson(haveUTR), + HaveGIINPage.path -> Json.toJson(haveGIIN) + ) ++ fiName ++ utr ++ giin + } yield obj + } + + lazy val fiNotRegistered: Arbitrary[UserAnswers] = Arbitrary { + for { + id <- nonEmptyString + address <- address.arbitrary + contactDetails <- firstAndSecondContactDetails.arbitrary + nameUTRandGIIN <- nameUTRandGIINDetails.arbitrary + obj = + setFields( + Json.obj() + ) ++ address ++ contactDetails ++ nameUTRandGIIN + } yield UserAnswers( + id = id, + data = obj + ) + } + + private def missingAnswersArb(arb: Arbitrary[UserAnswers], possibleAnswers: Seq[QuestionPage[_]]): Arbitrary[UserAnswers] = Arbitrary { + for { + answers <- arb.arbitrary + validPossibleAnswers = possibleAnswers.filter( + a => answers.data.keys.toSeq.contains(a.toString) + ) + n <- Gen.oneOf(1, validPossibleAnswers.length) + missingQuestions <- Gen.pick(n, validPossibleAnswers) + updatedAnswers = missingQuestions.foldLeft(answers) { + case (acc, page) => acc.remove(page).success.value + } + } yield updatedAnswers + } + + lazy val fiNotRegisteredMissingAnswers: Arbitrary[UserAnswers] = + missingAnswersArb( + fiNotRegistered, + Seq( + FirstContactEmailPage, + FirstContactHavePhonePage, + FirstContactNamePage, + FirstContactPhoneNumberPage, + HaveGIINPage, + HaveUniqueTaxpayerReferencePage, + IsThisAddressPage, + PostcodePage, + SelectAddressPage, + UkAddressPage, + WhatIsGIINPage, + WhatIsUniqueTaxpayerReferencePage, + WhereIsFIBasedPage, + SecondContactEmailPage, + SecondContactExistsPage, + SecondContactNamePage, + SecondContactPhoneNumberPage + ) + ) + +} diff --git a/test/controllers/SomeInformationMissingControllerSpec.scala b/test/controllers/SomeInformationMissingControllerSpec.scala index e9bc095f..891b8c82 100644 --- a/test/controllers/SomeInformationMissingControllerSpec.scala +++ b/test/controllers/SomeInformationMissingControllerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2024 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 controllers import base.SpecBase @@ -25,4 +41,5 @@ class SomeInformationMissingControllerSpec extends SpecBase { } } } + } diff --git a/test/utils/CheckYourAnswersValidatorSpec.scala b/test/utils/CheckYourAnswersValidatorSpec.scala new file mode 100644 index 00000000..d78d0b7a --- /dev/null +++ b/test/utils/CheckYourAnswersValidatorSpec.scala @@ -0,0 +1,87 @@ +/* + * Copyright 2024 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 utils + +import generators.{ModelGenerators, UserAnswersGenerator} +import models.UserAnswers +import org.scalatest.freespec.AnyFreeSpec +import org.scalatest.matchers.must.Matchers +import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks +import pages.addFinancialInstitution.{ + FirstContactEmailPage, + FirstContactHavePhonePage, + FirstContactNamePage, + FirstContactPhoneNumberPage, + HaveGIINPage, + HaveUniqueTaxpayerReferencePage, + IsThisAddressPage, + PostcodePage, + SecondContactEmailPage, + SecondContactExistsPage, + SecondContactNamePage, + SecondContactPhoneNumberPage, + SelectAddressPage, + UkAddressPage, + WhatIsGIINPage, + WhatIsUniqueTaxpayerReferencePage, + WhereIsFIBasedPage +} + +class CheckYourAnswersValidatorSpec extends AnyFreeSpec with Matchers with ModelGenerators with UserAnswersGenerator with ScalaCheckPropertyChecks { + + "CheckYourAnswersValidator" - { + + "not registered add FI journey" - { + + "return an empty list if no answers are missing" in { + forAll(fiNotRegistered.arbitrary) { + (userAnswers: UserAnswers) => + val result = CheckYourAnswersValidator(userAnswers).validate + result mustBe Nil + } + } + + "return missing answers" in { + forAll(fiNotRegisteredMissingAnswers.arbitrary) { + (userAnswers: UserAnswers) => + val result = CheckYourAnswersValidator(userAnswers).validate + result mustNot be(empty) + Set( + FirstContactEmailPage, + FirstContactHavePhonePage, + FirstContactNamePage, + FirstContactPhoneNumberPage, + HaveGIINPage, + HaveUniqueTaxpayerReferencePage, + IsThisAddressPage, + PostcodePage, + SelectAddressPage, + UkAddressPage, + WhatIsGIINPage, + WhatIsUniqueTaxpayerReferencePage, + WhereIsFIBasedPage, + SecondContactEmailPage, + SecondContactExistsPage, + SecondContactNamePage, + SecondContactPhoneNumberPage + ) must contain allElementsOf result + } + } + } + } + +} From 61220bbcbef388ac4f4e00baff88b2e5d2fcf894 Mon Sep 17 00:00:00 2001 From: matthewharris1 <33547722+matthewharris1@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:54:10 +0100 Subject: [PATCH 3/5] DAC6-3209 | Removed change from val name --- app/utils/CheckYourAnswersValidator.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/utils/CheckYourAnswersValidator.scala b/app/utils/CheckYourAnswersValidator.scala index 09c8115b..e6527cf1 100644 --- a/app/utils/CheckYourAnswersValidator.scala +++ b/app/utils/CheckYourAnswersValidator.scala @@ -41,7 +41,7 @@ sealed trait AddFIValidator { checkPage(FirstContactEmailPage) ).flatten ++ firstContactPhoneMissingAnswers - private def checkChangeSecContactDetailsMissingAnswers: Seq[Page] = + private def checkSecContactDetailsMissingAnswers: Seq[Page] = userAnswers.get(SecondContactExistsPage) match { case Some(true) => Seq( @@ -52,7 +52,7 @@ sealed trait AddFIValidator { case _ => Seq(SecondContactExistsPage) } - private[utils] def checkContactDetailsMissingAnswers = checkFirstContactMissingAnswers ++ checkChangeSecContactDetailsMissingAnswers + private[utils] def checkContactDetailsMissingAnswers = checkFirstContactMissingAnswers ++ checkSecContactDetailsMissingAnswers private[utils] def checkAddressMissingAnswers: Seq[Page] = (userAnswers.get(WhereIsFIBasedPage) match { case Some(true) => From d5bb59e567e41b05db9822d8e9c170afb707d595 Mon Sep 17 00:00:00 2001 From: matthewharris1 <33547722+matthewharris1@users.noreply.github.com> Date: Mon, 2 Sep 2024 15:18:35 +0100 Subject: [PATCH 4/5] DAC6-3209 | Added onsubmit route that was missed during conflict merging --- conf/app.routes | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/app.routes b/conf/app.routes index cd8c64cf..534c5cf9 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -145,5 +145,6 @@ POST /registered-business/check-answers controllers GET /financial-institution-added controllers.addFinancialInstitution.FinancialInstitutionAddedConfirmationController.onPageLoad GET /your-fis controllers.YourFinancialInstitutionsController.onPageLoad +POST /your-fis controllers.YourFinancialInstitutionsController.onSubmit() GET /problem/some-information-is-missing controllers.SomeInformationMissingController.onPageLoad() From ee2c9642d63c5ac6fe4484f8994fde2cc85a6105 Mon Sep 17 00:00:00 2001 From: matthewharris1 <33547722+matthewharris1@users.noreply.github.com> Date: Tue, 3 Sep 2024 10:07:29 +0100 Subject: [PATCH 5/5] DAC6-3209 | Fixed import and removed unused method --- .../generators/UserAnswersGenerator.scala | 16 --------------- .../utils/CheckYourAnswersValidatorSpec.scala | 20 +------------------ 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/test-utils/generators/UserAnswersGenerator.scala b/test-utils/generators/UserAnswersGenerator.scala index 6c65434d..63ef820a 100644 --- a/test-utils/generators/UserAnswersGenerator.scala +++ b/test-utils/generators/UserAnswersGenerator.scala @@ -50,22 +50,6 @@ trait UserAnswersGenerator extends UserAnswersEntryGenerators with TryValues { arbitrary[(WhereIsFIBasedPage.type, JsValue)] :: Nil - implicit lazy val arbitraryUserData: Arbitrary[UserAnswers] = Arbitrary { - for { - id <- nonEmptyString - data <- generators match { - case Nil => Gen.const(Map[QuestionPage[_], JsValue]()) - case _ => Gen.mapOf(oneOf(generators)) - } - } yield UserAnswers( - id = id, - data = data.foldLeft(Json.obj()) { - case (obj, (path, value)) => - obj.setObject(path.path, value).get - } - ) - } - private def genJsObj(gens: Gen[(QuestionPage[_], JsValue)]*): Gen[JsObject] = Gen.sequence[Seq[(QuestionPage[_], JsValue)], (QuestionPage[_], JsValue)](gens).map { seq => diff --git a/test/utils/CheckYourAnswersValidatorSpec.scala b/test/utils/CheckYourAnswersValidatorSpec.scala index d78d0b7a..8ae23996 100644 --- a/test/utils/CheckYourAnswersValidatorSpec.scala +++ b/test/utils/CheckYourAnswersValidatorSpec.scala @@ -21,25 +21,7 @@ import models.UserAnswers import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.must.Matchers import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks -import pages.addFinancialInstitution.{ - FirstContactEmailPage, - FirstContactHavePhonePage, - FirstContactNamePage, - FirstContactPhoneNumberPage, - HaveGIINPage, - HaveUniqueTaxpayerReferencePage, - IsThisAddressPage, - PostcodePage, - SecondContactEmailPage, - SecondContactExistsPage, - SecondContactNamePage, - SecondContactPhoneNumberPage, - SelectAddressPage, - UkAddressPage, - WhatIsGIINPage, - WhatIsUniqueTaxpayerReferencePage, - WhereIsFIBasedPage -} +import pages.addFinancialInstitution._ class CheckYourAnswersValidatorSpec extends AnyFreeSpec with Matchers with ModelGenerators with UserAnswersGenerator with ScalaCheckPropertyChecks {