From 9a202ea7c6285d5d331470b9d9e0dcb363bfe3d9 Mon Sep 17 00:00:00 2001
From: Pete Robinson <77154273+peterdrobinson@users.noreply.github.com>
Date: Tue, 7 Oct 2025 15:18:36 +0100
Subject: [PATCH 1/4] NGR-2538 - Added How Much Was The Lump Sum page
---
.../HowMuchWasTheLumpSumController.scala | 76 ++++++++++++
.../forms/HowMuchWasTheLumpSumForm.scala | 59 ++++++++++
.../navigation/Navigator.scala | 1 +
.../pages/HowMuchWasTheLumpSumPage.scala | 27 +++++
.../views/HowMuchWasTheLumpSumView.scala.html | 55 +++++++++
conf/app.routes | 8 +-
conf/messages | 8 +-
.../HowMuchWasTheLumpSumControllerSpec.scala | 111 ++++++++++++++++++
.../forms/HowMuchWasTheLumpSumFormSpec.scala | 108 +++++++++++++++++
.../views/HowMuchWasTheLumpSumViewSpec.scala | 71 +++++++++++
10 files changed, 522 insertions(+), 2 deletions(-)
create mode 100644 app/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumController.scala
create mode 100644 app/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumForm.scala
create mode 100644 app/uk/gov/hmrc/ngrraldfrontend/pages/HowMuchWasTheLumpSumPage.scala
create mode 100644 app/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumView.scala.html
create mode 100644 test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
create mode 100644 test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
create mode 100644 test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumController.scala b/app/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumController.scala
new file mode 100644
index 0000000..08b7018
--- /dev/null
+++ b/app/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumController.scala
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.controllers
+
+import play.api.i18n.I18nSupport
+import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
+import uk.gov.hmrc.ngrraldfrontend.actions.{AuthRetrievals, DataRetrievalAction}
+import uk.gov.hmrc.ngrraldfrontend.config.AppConfig
+import uk.gov.hmrc.ngrraldfrontend.models.forms.HowMuchWasTheLumpSumForm
+import uk.gov.hmrc.ngrraldfrontend.models.forms.HowMuchWasTheLumpSumForm.form
+import uk.gov.hmrc.ngrraldfrontend.models.{Mode, UserAnswers}
+import uk.gov.hmrc.ngrraldfrontend.navigation.Navigator
+import uk.gov.hmrc.ngrraldfrontend.pages.HowMuchWasTheLumpSumPage
+import uk.gov.hmrc.ngrraldfrontend.repo.SessionRepository
+import uk.gov.hmrc.ngrraldfrontend.views.html.HowMuchWasTheLumpSumView
+import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
+
+import javax.inject.{Inject, Singleton}
+import scala.concurrent.{ExecutionContext, Future}
+
+@Singleton
+class HowMuchWasTheLumpSumController @Inject()(howMuchWasTheLumpSumView: HowMuchWasTheLumpSumView,
+ authenticate: AuthRetrievals,
+ getData: DataRetrievalAction,
+ sessionRepository: SessionRepository,
+ navigator: Navigator,
+ mcc: MessagesControllerComponents)(implicit appConfig: AppConfig, ec: ExecutionContext)
+ extends FrontendController(mcc) with I18nSupport {
+
+
+ def show(mode: Mode): Action[AnyContent] = {
+ (authenticate andThen getData).async { implicit request =>
+ val preparedForm = request.userAnswers.getOrElse(UserAnswers(request.credId)).get(HowMuchWasTheLumpSumPage) match {
+ case None => form
+ case Some(value) => form.fill(HowMuchWasTheLumpSumForm(value))
+ }
+ Future.successful(Ok(howMuchWasTheLumpSumView(
+ form = preparedForm,
+ propertyAddress = request.property.addressFull,
+ mode = mode
+ )))
+ }
+ }
+
+ def submit(mode: Mode): Action[AnyContent] =
+ (authenticate andThen getData).async { implicit request =>
+ form.bindFromRequest().fold(
+ formWithErrors => {
+ Future.successful(BadRequest(howMuchWasTheLumpSumView(
+ form = formWithErrors,
+ propertyAddress = request.property.addressFull,
+ mode = mode
+ )))
+ },
+ lumpSumAmount =>
+ for {
+ updatedAnswers <- Future.fromTry(request.userAnswers.getOrElse(UserAnswers(request.credId)).set(HowMuchWasTheLumpSumPage, lumpSumAmount.lumpSum))
+ _ <- sessionRepository.set(updatedAnswers)
+ } yield Redirect(navigator.nextPage(HowMuchWasTheLumpSumPage, mode, updatedAnswers))
+ )
+ }
+}
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumForm.scala b/app/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumForm.scala
new file mode 100644
index 0000000..eceaa5e
--- /dev/null
+++ b/app/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumForm.scala
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.models.forms
+
+import play.api.data.*
+import play.api.data.Forms.*
+import play.api.data.format.Formatter
+import play.api.libs.json.{Json, OFormat}
+
+import scala.math.BigDecimal.RoundingMode
+import scala.util.Try
+
+
+final case class HowMuchWasTheLumpSumForm(lumpSum: BigDecimal)
+
+object HowMuchWasTheLumpSumForm extends CommonFormValidators {
+ implicit val format: OFormat[HowMuchWasTheLumpSumForm] = Json.format[HowMuchWasTheLumpSumForm]
+
+ private lazy val lumpSum = "how–much–was–the–lump–sum-value"
+ private lazy val lumpSumEmptyError = "howMuchWasTheLumpSum.empty.error"
+ private lazy val lumpSumMaxError = "howMuchWasTheLumpSum.tooLarge.error"
+ private lazy val lumpSumFormatError = "howMuchWasTheLumpSum.format.error"
+
+
+ def unapply(howMuchWasTheLumpSumForm: HowMuchWasTheLumpSumForm): Option[BigDecimal] = Some(howMuchWasTheLumpSumForm.lumpSum)
+
+ val form: Form[HowMuchWasTheLumpSumForm] = Form(
+ mapping(
+ lumpSum -> text()
+ .transform[String](_.strip().replaceAll("[£|,|\\s]", ""), identity)
+ .verifying(
+ firstError(
+ isNotEmpty(lumpSum, lumpSumEmptyError),
+ regexp(amountRegex.pattern(),lumpSumFormatError)
+ )
+ )
+ .transform[BigDecimal](BigDecimal(_).setScale(2, RoundingMode.HALF_UP), _.toString)
+ .verifying(
+ maximumValue[BigDecimal](BigDecimal("9999999.99"), lumpSumMaxError)
+ )
+ )(HowMuchWasTheLumpSumForm.apply)(HowMuchWasTheLumpSumForm.unapply)
+ )
+
+}
+
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala b/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
index 1ca2124..9849d1e 100644
--- a/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
+++ b/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
@@ -156,6 +156,7 @@ class Navigator @Inject()() {
case ConfirmBreakClausePage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.LandlordController.show(NormalMode) //TODO This needs to be amended when the journey is completed
//TODO Next page not made yet
case RentReviewPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.CheckRentFreePeriodController.show(NormalMode)
+ case HowMuchWasTheLumpSumPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.CheckRentFreePeriodController.show(NormalMode)
}
//TODO change to check your answers page
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/pages/HowMuchWasTheLumpSumPage.scala b/app/uk/gov/hmrc/ngrraldfrontend/pages/HowMuchWasTheLumpSumPage.scala
new file mode 100644
index 0000000..6757fc6
--- /dev/null
+++ b/app/uk/gov/hmrc/ngrraldfrontend/pages/HowMuchWasTheLumpSumPage.scala
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.pages
+
+import play.api.libs.json.JsPath
+
+case object HowMuchWasTheLumpSumPage extends QuestionPage[BigDecimal]{
+
+ override def toString: String = "howMuchWasTheLumpSumPage"
+
+ override def path: JsPath = JsPath \ toString
+
+}
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumView.scala.html b/app/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumView.scala.html
new file mode 100644
index 0000000..0794b99
--- /dev/null
+++ b/app/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumView.scala.html
@@ -0,0 +1,55 @@
+@*
+ * Copyright 2025 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.
+ *@
+
+@import uk.gov.hmrc.govukfrontend.views.html.components._
+@import uk.gov.hmrc.govukfrontend.views.Aliases._
+@import uk.gov.hmrc.ngrraldfrontend.views.html.components._
+@import uk.gov.hmrc.ngrraldfrontend.viewmodels.govuk.all._
+@import uk.gov.hmrc.ngrraldfrontend.config.AppConfig
+@import uk.gov.hmrc.ngrraldfrontend.models.forms.HowMuchWasTheLumpSumForm
+
+@this(
+layout: Layout,
+formHelper: FormWithCSRF,
+govukErrorSummary: GovukErrorSummary,
+inputText: components.InputText,
+saveAndContinueButton: saveAndContinueButton
+)
+
+@(form:Form[HowMuchWasTheLumpSumForm], propertyAddress: String, mode: Mode)(implicit request: RequestHeader, messages: Messages, appConfig: AppConfig)
+
+@layout(pageTitle = Some(messages("howMuchWasTheLumpSum.title")), showBackLink = true, fullWidth = false) {
+@formHelper(action = uk.gov.hmrc.ngrraldfrontend.controllers.routes.HowMuchWasTheLumpSumController.submit(mode), Symbol("autoComplete") -> "off") {
+@if(form.errors.nonEmpty) {
+@govukErrorSummary(ErrorSummaryViewModel(form))
+}
+@propertyAddress
+
@messages("howMuchWasTheLumpSum.title")
+
+@inputText(
+ form = form,
+ id = "how–much–was–the–lump–sum-value",
+ name = "how–much–was–the–lump–sum-value",
+ label = messages("howMuchWasTheLumpSum.title"),
+ isPageHeading = false,
+ hint = None,
+ isVisible = false,
+ classes = Some("govuk-!-width-two-thirds"),
+ prefix = Some(PrefixOrSuffix(content = Text("£")))
+)
+@saveAndContinueButton(msg = messages("service.continue"), isStartButton = false)
+}
+}
\ No newline at end of file
diff --git a/conf/app.routes b/conf/app.routes
index fc7de14..311a0ec 100644
--- a/conf/app.routes
+++ b/conf/app.routes
@@ -153,4 +153,10 @@ POST /repairs-and-insurance/change uk.gov.hmrc.n
GET /rent-review uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.show(mode: Mode = NormalMode)
POST /rent-review uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.submit(mode: Mode = NormalMode)
GET /rent-review/change uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.show(mode: Mode = CheckMode)
-POST /rent-review/change uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.submit(mode: Mode = CheckMode)
\ No newline at end of file
+POST /rent-review/change uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.submit(mode: Mode = CheckMode)
+
+#Rent review
+GET /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = NormalMode)
+POST /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = NormalMode)
+GET /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = CheckMode)
+POST /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = CheckMode)
\ No newline at end of file
diff --git a/conf/messages b/conf/messages
index 4c53dba..3ef7c78 100644
--- a/conf/messages
+++ b/conf/messages
@@ -408,4 +408,10 @@ rentReview.rentReviewMonthsYears.months.invalid.error = The number of months for
rentReview.rentReviewMonthsYears.months.maximum.12.error = The number of months for how often your rent is reviewed must be 12 or less
rentReview.rentReviewMonthsYears.months.maximum.11.error = The number of months for how often your rent is reviewed must be 11 or less
rentReview.rentReviewMonthsYears.years.invalid.error = The number of years for how often your rent is reviewed must be a number, like 2
-rentReview.rentReviewMonthsYears.years.maximum.1000.error = How often your rent is reviewed must be 1,000 years or less
\ No newline at end of file
+rentReview.rentReviewMonthsYears.years.maximum.1000.error = How often your rent is reviewed must be 1,000 years or less
+
+#How much was the lump sum
+howMuchWasTheLumpSum.title = How much was the lump sum?
+howMuchWasTheLumpSum.empty.error = Enter the lump sum, in pounds
+howMuchWasTheLumpSum.tooLarge.error = Lump sum must be £9,999,999.99 or less
+howMuchWasTheLumpSum.format.error = Lump sum must be a number, like 50,000
\ No newline at end of file
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
new file mode 100644
index 0000000..a195645
--- /dev/null
+++ b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.controllers
+
+import org.jsoup.Jsoup
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mockito.when
+import play.api.http.Status.{BAD_REQUEST, OK, SEE_OTHER}
+import play.api.test.FakeRequest
+import play.api.test.Helpers.{await, contentAsString, defaultAwaitTimeout, redirectLocation, status}
+import uk.gov.hmrc.http.{HeaderNames, NotFoundException}
+import uk.gov.hmrc.ngrraldfrontend.helpers.ControllerSpecSupport
+import uk.gov.hmrc.ngrraldfrontend.models.AgreementType.{NewAgreement, RenewedAgreement}
+import uk.gov.hmrc.ngrraldfrontend.models.registration.CredId
+import uk.gov.hmrc.ngrraldfrontend.models.{NormalMode, UserAnswers}
+import uk.gov.hmrc.ngrraldfrontend.pages.{HowMuchWasTheLumpSumPage, TellUsAboutYourNewAgreementPage, TellUsAboutYourRenewedAgreementPage}
+import uk.gov.hmrc.ngrraldfrontend.views.html.HowMuchWasTheLumpSumView
+
+import scala.concurrent.Future
+
+
+class HowMuchWasTheLumpSumControllerSpec extends ControllerSpecSupport {
+ val pageTitle = "How much was the lump sum?"
+ val view: HowMuchWasTheLumpSumView = inject[HowMuchWasTheLumpSumView]
+ val controllerNoProperty: HowMuchWasTheLumpSumController = new HowMuchWasTheLumpSumController(view, fakeAuth, fakeData(None), mockSessionRepository, mockNavigator, mcc)(mockConfig)
+ val controllerProperty: HowMuchWasTheLumpSumController = new HowMuchWasTheLumpSumController(view, fakeAuth, fakeDataProperty(Some(property),None), mockSessionRepository, mockNavigator, mcc)(mockConfig)
+ lazy val howMuchIsTotalAnnualRentAnswers: Option[UserAnswers] = UserAnswers("id").set(HowMuchWasTheLumpSumPage, BigDecimal(1234.67)).toOption
+ lazy val filledController: Option[UserAnswers] => HowMuchWasTheLumpSumController = answers => HowMuchWasTheLumpSumController(
+ view, fakeAuth, fakeDataProperty(Some(property), answers), mockSessionRepository, mockNavigator, mcc
+ )
+
+ "HowMuchWasTheLumpSumControllerSpec" must {
+ "method show" must {
+ "Return OK and the correct view" in {
+ val result = controllerProperty.show(NormalMode)(authenticatedFakeRequest)
+ status(result) mustBe OK
+ val content = contentAsString(result)
+ content must include(pageTitle)
+ }
+ "Return OK and the correct with prepopulated answers" in {
+ val result = filledController(howMuchIsTotalAnnualRentAnswers).show(NormalMode)(authenticatedFakeRequest)
+ status(result) mustBe OK
+ val content = contentAsString(result)
+ val document = Jsoup.parse(content)
+ document.select("input[name=how–much–was–the–lump–sum-value]").attr("value") mustBe "1234.67"
+ }
+ "Return NotFoundException when property is not found in the mongo" in {
+ when(mockNGRConnector.getLinkedProperty(any[CredId])(any())).thenReturn(Future.successful(None))
+ val exception = intercept[NotFoundException] {
+ await(controllerNoProperty.show(NormalMode)(authenticatedFakeRequest))
+ }
+ exception.getMessage contains "Could not find answers in backend mongo" mustBe true
+ }
+ }
+
+ "method submit" must {
+ "Return See_Other and the correct view if its a renewedAgreement" in {
+ when(mockSessionRepository.set(any())).thenReturn(Future.successful(true))
+ val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", "10000"))
+ .withHeaders(HeaderNames.authorisation -> "Bearer 1")
+
+ val result = filledController(renewedAgreementAnswers).submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
+ status(result) mustBe SEE_OTHER
+ redirectLocation(result) mustBe Some(routes.CheckRentFreePeriodController.show(NormalMode).url)
+ }
+ "Return See_Other and the correct view if its a newAgreement" in {
+
+ when(mockSessionRepository.set(any())).thenReturn(Future.successful(true))
+ val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", "10000"))
+ .withHeaders(HeaderNames.authorisation -> "Bearer 1")
+
+ val result = filledController(newAgreementAnswers).submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
+ status(result) mustBe SEE_OTHER
+ redirectLocation(result) mustBe Some(routes.CheckRentFreePeriodController.show(NormalMode).url)
+ }
+ "Return BAD_REQUEST for missing input and the correct view" in {
+ val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", ""))
+ .withHeaders(HeaderNames.authorisation -> "Bearer 1")
+
+ val result = controllerProperty.submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
+ status(result) mustBe BAD_REQUEST
+ }
+ "Return Exception if no address is in the mongo" in {
+ val fakePostRequest = FakeRequest(routes.WhatTypeOfLeaseRenewalController.submit(NormalMode))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", ""))
+ .withHeaders(HeaderNames.authorisation -> "Bearer 1")
+ val exception = intercept[NotFoundException] {
+ await(controllerNoProperty.submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest)))
+ }
+ exception.getMessage contains "Could not find answers in backend mongo" mustBe true
+ }
+ }
+ }
+}
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
new file mode 100644
index 0000000..41770e3
--- /dev/null
+++ b/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.models.forms
+
+import org.scalatest.matchers.should.Matchers
+import org.scalatest.matchers.should.Matchers.{should, shouldBe}
+import org.scalatest.wordspec.AnyWordSpec
+import play.api.data.FormError
+import play.api.libs.json.Json
+
+import scala.collection.immutable.ArraySeq
+
+class HowMuchWasTheLumpSumFormSpec extends AnyWordSpec with Matchers {
+
+ "HowMuchWasTheLumpSumForm" should {
+
+ "bind valid input" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "123456.78")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe false
+ boundForm.value shouldBe Some(HowMuchWasTheLumpSumForm(BigDecimal("123456.78")))
+ }
+
+ "bind amount with commas" in {
+ val data = Map(
+ "how–much–was–the–lump–sum-value" -> "9,999,999.99",
+ )
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe false
+ boundForm.value shouldBe Some(HowMuchWasTheLumpSumForm(BigDecimal("9999999.99")))
+ }
+
+ "fail to bind empty input" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe true
+ boundForm.errors should contain(FormError("how–much–was–the–lump–sum-value", List("howMuchWasTheLumpSum.empty.error"), ArraySeq("how–much–was–the–lump–sum-value")))
+ }
+
+ "fail to bind non-numeric input" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "abc")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.errors should contain(FormError("how–much–was–the–lump–sum-value", List("howMuchWasTheLumpSum.format.error"), ArraySeq("([0-9]+\\.[0-9]+|[0-9]+)")))
+ }
+
+ "fail to bind input greater than 9999999.99" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "10000000.00")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe true
+ boundForm.errors should contain(FormError("how–much–was–the–lump–sum-value", List("howMuchWasTheLumpSum.tooLarge.error"), ArraySeq(9999999.99)))
+ }
+
+ "bind edge case of exactly 9999999.99" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "9999999.99")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe false
+ boundForm.value shouldBe Some(HowMuchWasTheLumpSumForm(BigDecimal("9999999.99")))
+ }
+ }
+
+ "serialize to JSON correctly" in {
+ val form = HowMuchWasTheLumpSumForm(BigDecimal("9999999.99"))
+ val json = Json.toJson(form)
+
+ json shouldBe Json.obj(
+ "lumpSum" -> 9999999.99
+ )
+ }
+
+ "deserialize from JSON correctly" in {
+ val json = Json.obj(
+ "lumpSum" -> 9999999.99
+ )
+ val result = json.validate[HowMuchWasTheLumpSumForm]
+
+ result.isSuccess shouldBe true
+ result.get shouldBe HowMuchWasTheLumpSumForm(BigDecimal("9999999.99"))
+ }
+
+ "fail deserialization if value is missing" in {
+ val json = Json.obj()
+ val result = json.validate[HowMuchWasTheLumpSumForm]
+
+ result.isError shouldBe true
+ }
+}
+
+
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
new file mode 100644
index 0000000..08088bd
--- /dev/null
+++ b/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2025 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.ngrraldfrontend.views
+
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import uk.gov.hmrc.ngrraldfrontend.helpers.ViewBaseSpec
+import uk.gov.hmrc.ngrraldfrontend.models.NormalMode
+import uk.gov.hmrc.ngrraldfrontend.models.components.*
+import uk.gov.hmrc.ngrraldfrontend.models.forms.HowMuchWasTheLumpSumForm
+import uk.gov.hmrc.ngrraldfrontend.views.html.HowMuchWasTheLumpSumView
+
+class HowMuchWasTheLumpSumViewSpec extends ViewBaseSpec {
+ lazy val view: HowMuchWasTheLumpSumView = inject[HowMuchWasTheLumpSumView]
+
+ object Strings {
+ val heading = "How much was the lump sum?"
+ val saveAndContinue = "Continue"
+ }
+
+ object Selectors {
+ val heading = "#main-content > div > div.govuk-grid-column-two-thirds > form > h1"
+ val saveAndContinue = "#continue"
+ }
+
+ val address = "5 Brixham Marina, Berry Head Road, Brixham, Devon, TQ5 9BW"
+
+ val form = HowMuchWasTheLumpSumForm.form.fillAndValidate(HowMuchWasTheLumpSumForm(10000))
+
+ "TellUsAboutYourNewAgreementView" must {
+ val HowMuchWasTheLumpSumView = view(form, address, NormalMode)
+ lazy implicit val document: Document = Jsoup.parse(HowMuchWasTheLumpSumView.body)
+ val htmlApply = view.apply(form, address, NormalMode).body
+ val htmlRender = view.render(form, address, NormalMode, request, messages, mockConfig).body
+ lazy val htmlF = view.f(form, address, NormalMode)
+
+ "htmlF is not empty" in {
+ htmlF.toString() must not be empty
+ }
+
+ "apply must be the same as render" in {
+ htmlApply mustBe htmlRender
+ }
+
+ "render is not empty" in {
+ htmlRender must not be empty
+ }
+
+ "show correct heading" in {
+ elementText(Selectors.heading) mustBe Strings.heading
+ }
+
+ "show correct continue button" in {
+ elementText(Selectors.saveAndContinue) mustBe Strings.saveAndContinue
+ }
+ }
+}
From 18e46e56b57d34b4f132d3ae31d8686a04e175c2 Mon Sep 17 00:00:00 2001
From: Pete Robinson <77154273+peterdrobinson@users.noreply.github.com>
Date: Tue, 7 Oct 2025 15:20:13 +0100
Subject: [PATCH 2/4] NGR-1538 - Added note to Nav
---
app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala b/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
index 9849d1e..205710a 100644
--- a/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
+++ b/app/uk/gov/hmrc/ngrraldfrontend/navigation/Navigator.scala
@@ -156,7 +156,7 @@ class Navigator @Inject()() {
case ConfirmBreakClausePage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.LandlordController.show(NormalMode) //TODO This needs to be amended when the journey is completed
//TODO Next page not made yet
case RentReviewPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.CheckRentFreePeriodController.show(NormalMode)
- case HowMuchWasTheLumpSumPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.CheckRentFreePeriodController.show(NormalMode)
+ case HowMuchWasTheLumpSumPage => _ => uk.gov.hmrc.ngrraldfrontend.controllers.routes.CheckRentFreePeriodController.show(NormalMode) //TODO This needs to be amended when the journey is completed
}
//TODO change to check your answers page
From 8f5c58369146bbdd5d6d28d296cc9d49e965e7c5 Mon Sep 17 00:00:00 2001
From: Pete Robinson <77154273+peterdrobinson@users.noreply.github.com>
Date: Fri, 10 Oct 2025 10:23:44 +0100
Subject: [PATCH 3/4] WIP
---
conf/app.routes | 8 ++++----
.../controllers/HowMuchWasTheLumpSumControllerSpec.scala | 3 +++
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/conf/app.routes b/conf/app.routes
index 311a0ec..3bd52f3 100644
--- a/conf/app.routes
+++ b/conf/app.routes
@@ -156,7 +156,7 @@ GET /rent-review/change uk.gov.hmrc.ngrraldfron
POST /rent-review/change uk.gov.hmrc.ngrraldfrontend.controllers.RentReviewController.submit(mode: Mode = CheckMode)
#Rent review
-GET /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = NormalMode)
-POST /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = NormalMode)
-GET /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = CheckMode)
-POST /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = CheckMode)
\ No newline at end of file
+GET /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = NormalMode)
+POST /how-much-was-the-lump-sum uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = NormalMode)
+GET /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.show(mode: Mode = CheckMode)
+POST /how-much-was-the-lump-sum/change uk.gov.hmrc.ngrraldfrontend.controllers.HowMuchWasTheLumpSumController.submit(mode: Mode = CheckMode)
\ No newline at end of file
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
index a195645..d7ac586 100644
--- a/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
+++ b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
@@ -96,6 +96,9 @@ class HowMuchWasTheLumpSumControllerSpec extends ControllerSpecSupport {
val result = controllerProperty.submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
status(result) mustBe BAD_REQUEST
+ val content = contentAsString(result)
+ content must include(pageTitle)
+ content must include("Enter the lump sum, in pounds")
}
"Return Exception if no address is in the mongo" in {
val fakePostRequest = FakeRequest(routes.WhatTypeOfLeaseRenewalController.submit(NormalMode))
From 15b63fbbb238940c2b98476637890f5f81a805dc Mon Sep 17 00:00:00 2001
From: Pete Robinson <77154273+peterdrobinson@users.noreply.github.com>
Date: Fri, 10 Oct 2025 15:36:35 +0100
Subject: [PATCH 4/4] NGR-2538 - amended as per Anna's comments
---
.../HowMuchWasTheLumpSumControllerSpec.scala | 30 +++++++------------
.../forms/HowMuchWasTheLumpSumFormSpec.scala | 9 ++++++
.../views/HowMuchWasTheLumpSumViewSpec.scala | 5 ++++
3 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
index d7ac586..236ec08 100644
--- a/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
+++ b/test/uk/gov/hmrc/ngrraldfrontend/controllers/HowMuchWasTheLumpSumControllerSpec.scala
@@ -68,37 +68,27 @@ class HowMuchWasTheLumpSumControllerSpec extends ControllerSpecSupport {
}
"method submit" must {
- "Return See_Other and the correct view if its a renewedAgreement" in {
- when(mockSessionRepository.set(any())).thenReturn(Future.successful(true))
- val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
- .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", "10000"))
- .withHeaders(HeaderNames.authorisation -> "Bearer 1")
-
- val result = filledController(renewedAgreementAnswers).submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
- status(result) mustBe SEE_OTHER
- redirectLocation(result) mustBe Some(routes.CheckRentFreePeriodController.show(NormalMode).url)
- }
- "Return See_Other and the correct view if its a newAgreement" in {
-
- when(mockSessionRepository.set(any())).thenReturn(Future.successful(true))
+ "Return BAD_REQUEST for missing input and the correct view" in {
val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
- .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", "10000"))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", ""))
.withHeaders(HeaderNames.authorisation -> "Bearer 1")
- val result = filledController(newAgreementAnswers).submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
- status(result) mustBe SEE_OTHER
- redirectLocation(result) mustBe Some(routes.CheckRentFreePeriodController.show(NormalMode).url)
+ val result = controllerProperty.submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
+ status(result) mustBe BAD_REQUEST
+ val content = contentAsString(result)
+ content must include(pageTitle)
+ content must include("Enter the lump sum, in pounds")
}
- "Return BAD_REQUEST for missing input and the correct view" in {
+ "Return BAD_REQUEST for incorrect input and the correct view" in {
val fakePostRequest = FakeRequest(routes.HowMuchWasTheLumpSumController.submit(NormalMode))
- .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", ""))
+ .withFormUrlEncodedBody(("how–much–was–the–lump–sum-value", "xyz"))
.withHeaders(HeaderNames.authorisation -> "Bearer 1")
val result = controllerProperty.submit(NormalMode)(authenticatedFakePostRequest(fakePostRequest))
status(result) mustBe BAD_REQUEST
val content = contentAsString(result)
content must include(pageTitle)
- content must include("Enter the lump sum, in pounds")
+ content must include("Lump sum must be a number, like 50,000")
}
"Return Exception if no address is in the mongo" in {
val fakePostRequest = FakeRequest(routes.WhatTypeOfLeaseRenewalController.submit(NormalMode))
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
index 41770e3..79f6dd1 100644
--- a/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
+++ b/test/uk/gov/hmrc/ngrraldfrontend/models/forms/HowMuchWasTheLumpSumFormSpec.scala
@@ -36,6 +36,15 @@ class HowMuchWasTheLumpSumFormSpec extends AnyWordSpec with Matchers {
boundForm.value shouldBe Some(HowMuchWasTheLumpSumForm(BigDecimal("123456.78")))
}
+ "bind valid input when rounding up" in {
+ val data = Map("how–much–was–the–lump–sum-value" -> "123456.78561")
+ val boundForm = HowMuchWasTheLumpSumForm.form.bind(data)
+
+ boundForm.hasErrors shouldBe false
+ boundForm.value shouldBe Some(HowMuchWasTheLumpSumForm(BigDecimal("123456.79")))
+ }
+
+
"bind amount with commas" in {
val data = Map(
"how–much–was–the–lump–sum-value" -> "9,999,999.99",
diff --git a/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala b/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
index 08088bd..8e18536 100644
--- a/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
+++ b/test/uk/gov/hmrc/ngrraldfrontend/views/HowMuchWasTheLumpSumViewSpec.scala
@@ -34,6 +34,7 @@ class HowMuchWasTheLumpSumViewSpec extends ViewBaseSpec {
object Selectors {
val heading = "#main-content > div > div.govuk-grid-column-two-thirds > form > h1"
+ val textInput = "#how–much–was–the–lump–sum-value"
val saveAndContinue = "#continue"
}
@@ -63,6 +64,10 @@ class HowMuchWasTheLumpSumViewSpec extends ViewBaseSpec {
"show correct heading" in {
elementText(Selectors.heading) mustBe Strings.heading
}
+
+ "show correct textInput" in {
+ elementText(Selectors.textInput) contains("£")
+ }
"show correct continue button" in {
elementText(Selectors.saveAndContinue) mustBe Strings.saveAndContinue