From a11668184e43e44d404cff193654766bb2892e94 Mon Sep 17 00:00:00 2001 From: Berna Yasar Date: Fri, 11 Oct 2024 15:57:45 +0100 Subject: [PATCH] DL-13367 (#453) * DL-13367 * wip * DL-13367: Refactoring tests * wip * Fixing tests * Fixing tests * DL-13367 * Review comments --------- Co-authored-by: Byasar3 Co-authored-by: Gaurav Sood <88654936+daglisood@users.noreply.github.com> --- ...opertyDetailsDateOfRevalueController.scala | 46 ++-- ...tyDetailsDateOfRevalueControllerSpec.scala | 229 +++++++----------- .../PropertyDetailsTestFixture.scala | 135 +++++++++++ test/testhelpers/MockAuthUtil.scala | 40 ++- 4 files changed, 270 insertions(+), 180 deletions(-) create mode 100644 test/controllers/propertyDetails/PropertyDetailsTestFixture.scala diff --git a/app/controllers/propertyDetails/PropertyDetailsDateOfRevalueController.scala b/app/controllers/propertyDetails/PropertyDetailsDateOfRevalueController.scala index 288200ba..b022aeda 100644 --- a/app/controllers/propertyDetails/PropertyDetailsDateOfRevalueController.scala +++ b/app/controllers/propertyDetails/PropertyDetailsDateOfRevalueController.scala @@ -19,15 +19,14 @@ package controllers.propertyDetails import config.ApplicationConfig import connectors.{BackLinkCacheConnector, DataCacheConnector} import controllers.auth.{AuthAction, ClientHelper} +import forms.PropertyDetailsForms._ +import models._ +import play.api.i18n.{Messages, MessagesImpl} import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} import services.{PropertyDetailsCacheSuccessResponse, PropertyDetailsService, ServiceInfoService} import uk.gov.hmrc.play.bootstrap.controller.WithUnsafeDefaultFormBinding import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController -import forms.PropertyDetailsForms._ -import models.DateOfRevalue -import play.api.i18n.{Messages, MessagesImpl} -import play.twirl.api.HtmlFormat -import utils.AtedConstants.{DateOfRevalueConstant, SelectedPreviousReturn} +import utils.AtedConstants._ import utils.AtedUtils import javax.inject.Inject @@ -47,6 +46,9 @@ class PropertyDetailsDateOfRevalueController @Inject()(mcc: MessagesControllerCo implicit val ec: ExecutionContext = mcc.executionContext val controllerId: String = "PropertyDetailsDateOfRevalueController" + val dateFields: (String, String) = ("dateOfRevalue", messages("ated.property-details-value.dateOfRevalue.messageKey")) + + implicit lazy val messages: Messages = MessagesImpl(mcc.langs.availables.head, messagesApi) def view(id: String): Action[AnyContent] = Action.async { implicit request => authAction.authorisedAction { implicit authContext => @@ -76,10 +78,6 @@ class PropertyDetailsDateOfRevalueController @Inject()(mcc: MessagesControllerCo } } - implicit lazy val messages: Messages = MessagesImpl(mcc.langs.availables.head, messagesApi) - - val dateFields: (String, String) = ("dateOfRevalue", messages("ated.property-details-value.dateOfRevalue.messageKey")) - def save(id: String, periodKey: Int, mode: Option[String]): Action[AnyContent] = Action.async { implicit request => authAction.authorisedAction { implicit authContext => ensureClientContext { @@ -87,15 +85,33 @@ class PropertyDetailsDateOfRevalueController @Inject()(mcc: MessagesControllerCo serviceInfoService.getPartial.flatMap { serviceInfoContent => validateDateOfRevalue(periodKey, propertyDetailsDateOfRevalueForm.bindFromRequest(), dateFields).fold( formWithError => { - currentBackLink.map(backLink => (BadRequest(template(id, periodKey, formWithError, None, HtmlFormat.empty, None)))) + currentBackLink.map(backLink => BadRequest(template(id, periodKey, formWithError, mode, serviceInfoContent, backLink))) }, dateOfRevalue => { dataCacheConnector.saveFormData[DateOfRevalue](DateOfRevalueConstant, dateOfRevalue) - redirectWithBackLink( - isFullTaxPeriodController.controllerId, - controllers.propertyDetails.routes.IsFullTaxPeriodController.view(id), - Some(controllers.propertyDetails.routes.PropertyDetailsDateOfRevalueController.view(id).url) - ) + + val propertyDetailsFuture: Future[PropertyDetailsRevalued] = for { + hasPropertyBeenRevalued <- dataCacheConnector.fetchAndGetFormData[HasBeenRevalued](HasPropertyBeenRevalued) + revaluedValue <- dataCacheConnector.fetchAndGetFormData[PropertyDetailsNewValuation](propertyDetailsNewValuationValue) + dateOfChange <- dataCacheConnector.fetchAndGetFormData[DateOfChange](FortyThousandValueDateOfChange) + } yield { + PropertyDetailsRevalued( + isPropertyRevalued = hasPropertyBeenRevalued.flatMap(_.isPropertyRevalued), + revaluedValue = revaluedValue.flatMap(_.revaluedValue), + revaluedDate = dateOfRevalue.dateOfRevalue, + partAcqDispDate = dateOfChange.flatMap(_.dateOfChange) + ) + } + propertyDetailsFuture.flatMap { propertyDetails => + for { + _ <- propertyDetailsService.saveDraftPropertyDetailsRevalued(id, propertyDetails) + result <- redirectWithBackLink( + isFullTaxPeriodController.controllerId, + controllers.propertyDetails.routes.IsFullTaxPeriodController.view(id), + Some(controllers.propertyDetails.routes.PropertyDetailsDateOfRevalueController.view(id).url) + ) + } yield result + } } ) } diff --git a/test/controllers/propertyDetails/PropertyDetailsDateOfRevalueControllerSpec.scala b/test/controllers/propertyDetails/PropertyDetailsDateOfRevalueControllerSpec.scala index 7fb1e101..7cb8826b 100644 --- a/test/controllers/propertyDetails/PropertyDetailsDateOfRevalueControllerSpec.scala +++ b/test/controllers/propertyDetails/PropertyDetailsDateOfRevalueControllerSpec.scala @@ -16,79 +16,22 @@ package controllers.propertyDetails -import builders.{PropertyDetailsBuilder, SessionBuilder} -import config.ApplicationConfig -import connectors.{BackLinkCacheConnector, DataCacheConnector} -import controllers.auth.AuthAction -import org.mockito.ArgumentMatchers +import builders.SessionBuilder import org.mockito.Mockito.when -import org.scalatestplus.mockito.MockitoSugar -import org.scalatestplus.play.PlaySpec -import org.scalatestplus.play.guice.GuiceOneServerPerSuite import play.api.http.Status.{BAD_REQUEST, OK, SEE_OTHER} -import play.api.i18n.{Lang, MessagesApi, MessagesImpl} import play.api.libs.json.{JsValue, Json} -import play.api.mvc.MessagesControllerComponents import play.api.test.FakeRequest import play.api.test.Helpers.{contentAsString, defaultAwaitTimeout, redirectLocation, status} -import services.{PropertyDetailsCacheSuccessResponse, PropertyDetailsService, ServiceInfoService} -import testhelpers.MockAuthUtil -import uk.gov.hmrc.auth.core.AffinityGroup -import uk.gov.hmrc.http.HeaderCarrier -import utils.AtedConstants.DelegatedClientAtedRefNumber -import views.html.BtaNavigationLinks -import views.html.propertyDetails.propertyDetailsDateOfRevalue - -import java.util.UUID -import scala.concurrent.Future - -class PropertyDetailsDateOfRevalueControllerSpec extends PlaySpec with GuiceOneServerPerSuite with MockitoSugar with MockAuthUtil{ - - implicit val mockAppConfig: ApplicationConfig = mock[ApplicationConfig] - implicit lazy val hc: HeaderCarrier = HeaderCarrier() - - val mockMcc: MessagesControllerComponents = app.injector.instanceOf[MessagesControllerComponents] - val mockPropertyDetailsService: PropertyDetailsService = mock[PropertyDetailsService] - val mockDataCacheConnector: DataCacheConnector = mock[DataCacheConnector] - val mockBackLinkCacheConnector: BackLinkCacheConnector = mock[BackLinkCacheConnector] - val mockNewValuationController: PropertyDetailsNewValuationController = mock[PropertyDetailsNewValuationController] - val mockIsFullTaxPeriodController: IsFullTaxPeriodController = mock[IsFullTaxPeriodController] - val messagesApi: MessagesApi = app.injector.instanceOf[MessagesApi] - lazy implicit val messages: MessagesImpl = MessagesImpl(Lang("en-GB"), messagesApi) - val btaNavigationLinksView: BtaNavigationLinks = app.injector.instanceOf[BtaNavigationLinks] - val mockServiceInfoService: ServiceInfoService = mock[ServiceInfoService] - val injectedViewInstance: propertyDetailsDateOfRevalue = app.injector.instanceOf[views.html.propertyDetails.propertyDetailsDateOfRevalue] - - class Setup { - val mockAuthAction: AuthAction = new AuthAction( - mockAppConfig, - mockDelegationService, - mockAuthConnector - ) - - val testController: PropertyDetailsDateOfRevalueController = new PropertyDetailsDateOfRevalueController( - mockMcc, - mockAuthAction, - mockServiceInfoService, - injectedViewInstance, - mockPropertyDetailsService, - mockBackLinkCacheConnector, - mockDataCacheConnector, - mockIsFullTaxPeriodController - ) - - - val customBtaNavigationLinks = btaNavigationLinksView()(messages, mockAppConfig) - - val userId = s"user-${UUID.randomUUID}" - val propertyDetails = PropertyDetailsBuilder.getPropertyDetails("1", Some("z11 1zz")).copy(value = None) - } +import utils.AtedConstants.HasPropertyBeenRevalued + +import java.time.LocalDate + +class PropertyDetailsDateOfRevalueControllerSpec extends PropertyDetailsTestFixture { "PropertyDetailsDateOfRevalueController.view" must { "redirect to the unauthorised page" when { - "user fails authentication" in new Setup { - val authMock = authResultDefault(AffinityGroup.Organisation, invalidEnrolmentSet) - setInvalidAuthMocks(authMock) + "user fails authentication" in { + setupAuthForOrganisation(invalidEnrolmentSet) val result = testController.view("1").apply(SessionBuilder.buildRequestWithSession(userId)) status(result) mustBe SEE_OTHER redirectLocation(result).get must include("ated/unauthorised") @@ -96,42 +39,30 @@ class PropertyDetailsDateOfRevalueControllerSpec extends PlaySpec with GuiceOneS } "render the date of revalue page" when { - "newRevaluedFeature flag is set to true" in new Setup { - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) - when(mockAppConfig.newRevaluedFeature).thenReturn(true) - when(mockServiceInfoService.getPartial(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(customBtaNavigationLinks)) - when(mockDataCacheConnector.fetchAtedRefData[String](ArgumentMatchers.eq(DelegatedClientAtedRefNumber))(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(Some("XN1200000100001"))) - when(mockDataCacheConnector.fetchAndGetFormData[Boolean](ArgumentMatchers.any()) - (ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockBackLinkCacheConnector.fetchAndGetBackLink(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockPropertyDetailsService.retrieveDraftPropertyDetails(ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(PropertyDetailsCacheSuccessResponse(propertyDetails))) + "newRevaluedFeature flag is set to true" in { + setupAuthForOrganisation() + setupCommonMockExpectations(true) + setupPropertyDetailServiceMockExpectations() val result = testController.view("1").apply(SessionBuilder.buildRequestWithSession(userId)) status(result) mustBe OK } } "redirect to home page" when { - "newRevaluedFeature flag is set to false" in new Setup { - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) + "newRevaluedFeature flag is set to false" in { + setupAuthForOrganisation() when(mockAppConfig.newRevaluedFeature).thenReturn(false) val result = testController.view("1").apply(SessionBuilder.buildRequestWithSession(userId)) status(result) mustBe SEE_OTHER redirectLocation(result).get must include("ated/home") } } - "for page errors, return BAD_REQUEST" in new Setup { + + "for page errors, return BAD_REQUEST" in { + setupAuthForOrganisation() + setupCommonMockExpectations(true) + setupPropertyDetailServiceMockExpectations() val inputJson: JsValue = Json.obj() - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) - when(mockAppConfig.newRevaluedFeature).thenReturn(true) - when(mockServiceInfoService.getPartial(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(customBtaNavigationLinks)) - when(mockDataCacheConnector.fetchAtedRefData[String](ArgumentMatchers.eq(DelegatedClientAtedRefNumber))(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(Some("XN1200000100001"))) - when(mockDataCacheConnector.fetchAndGetFormData[Boolean](ArgumentMatchers.any()) - (ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockBackLinkCacheConnector.fetchAndGetBackLink(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockPropertyDetailsService.saveDraftPropertyDetailsRevalued(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(OK)) val result = testController.save("1", 2015, None).apply(SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), userId)) status(result) mustBe BAD_REQUEST contentAsString(result) must include("There is a problem") @@ -140,100 +71,107 @@ class PropertyDetailsDateOfRevalueControllerSpec extends PlaySpec with GuiceOneS "PropertyDetailsDateOfRevalueController.save" must { "redirect to the unauthorised page" when { - "user fails authentication" in new Setup { - val authMock = authResultDefault(AffinityGroup.Organisation, invalidEnrolmentSet) - setInvalidAuthMocks(authMock) + "user fails authentication" in { + setupAuthForOrganisation(invalidEnrolmentSet) val result = testController.view("1").apply(SessionBuilder.buildRequestWithSession(userId)) status(result) mustBe SEE_OTHER redirectLocation(result).get must include("ated/unauthorised") } } + "collect information from cache and save to database" when { + "newRevaluedFeature flag is set to true and save invoked for a valid period" in { + val inputJson: JsValue = Json.obj( + "dateOfRevalue" -> Json.obj( + "day" -> 1, + "month" -> 4, + "year" -> 2020 + ) + ) + setupAuthForOrganisation() + setupCommonMockExpectations(true) + setupDataCacheConnectorExpectations( + newValuation = Some(BigDecimal.valueOf(1000000)), + hasPropertyBeenRevalued = Some(true), + dateOfRevaluationChange = Some(LocalDate.of(2021, 6, 15)) + ) + setupPropertyDetailServiceMockExpectations() + + + val result = testController.save("1", 2020, None).apply(SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), userId)) + status(result) mustBe SEE_OTHER + redirectLocation(result).get must include("ated/liability/create/full-tax-period/view") + + verifyPropertyDetailsService(Some(true), Some(1000000), Some(LocalDate.of(2020, 4, 1)), Some(LocalDate.of(2021, 6, 15))) + verifyDataCacheConnectorRetursHasBeenRevalued(HasPropertyBeenRevalued) + verifySaveBackLinkIsCalled + } + } + "redirect to next page: full tax period" when { - "newRevaluedFeature flag is set to true and user enters valid date" in new Setup { - val day = "1" - val month = "4" - val year = "2015" + "newRevaluedFeature flag is set to true and user enters valid date" in { val inputJson: JsValue = Json.obj( "dateOfRevalue" -> Json.obj( - "day" -> day, - "month" -> month, - "year" -> year + "day" -> "1", + "month" -> "4", + "year" -> "2015" ) ) - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) - when(mockAppConfig.newRevaluedFeature).thenReturn(true) - when(mockServiceInfoService.getPartial(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(customBtaNavigationLinks)) - when(mockDataCacheConnector.fetchAtedRefData[String](ArgumentMatchers.eq(DelegatedClientAtedRefNumber))(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(Some("XN1200000100001"))) - when(mockDataCacheConnector.fetchAndGetFormData[Boolean](ArgumentMatchers.any()) - (ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockBackLinkCacheConnector.saveBackLink(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockPropertyDetailsService.saveDraftPropertyDetailsRevalued(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(OK)) - val result = testController.save("1", 2015, None).apply(SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), userId)) + setupAuthForOrganisation() + setupCommonMockExpectations(true) + setupPropertyDetailServiceMockExpectations() + + val result = testController.save("1", 2015, None). + apply( + SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), + userId)) status(result) mustBe SEE_OTHER redirectLocation(result).get must include("ated/liability/create/full-tax-period/view") } } "return BAD_REQUEST with error message for invalid date" when { - "user enters an invalid date (31st of February)" in new Setup { - val day = "31" - val month = "2" - val year = "2024" + "user enters an invalid date (31st of February)" in { val inputJson: JsValue = Json.obj( "dateOfRevalue" -> Json.obj( - "day" -> day, - "month" -> month, - "year" -> year + "day" -> "31", + "month" -> "2", + "year" -> "2024" ) ) - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) - when(mockAppConfig.newRevaluedFeature).thenReturn(true) - when(mockServiceInfoService.getPartial(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(customBtaNavigationLinks)) - when(mockDataCacheConnector.fetchAtedRefData[String](ArgumentMatchers.eq(DelegatedClientAtedRefNumber))(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(Some("XN1200000100001"))) - when(mockDataCacheConnector.fetchAndGetFormData[Boolean](ArgumentMatchers.any()) - (ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockBackLinkCacheConnector.saveBackLink(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockPropertyDetailsService.saveDraftPropertyDetailsRevalued(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(OK)) - val result = testController.save("1", 2015, None).apply(SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), userId)) + setupAuthForOrganisation() + setupCommonMockExpectations(true) + setupPropertyDetailServiceMockExpectations() + val result = testController.save("1", 2015, None) + .apply( + SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), + userId)) status(result) mustBe BAD_REQUEST contentAsString(result) must include("There is a problem") } } "return BAD_REQUEST with error message for missing date fields" when { - "user omits some date fields" in new Setup { - val day = "" - val month = "4" - val year = "2024" + "user omits some date fields" in { val inputJson: JsValue = Json.obj( "dateOfRevalue" -> Json.obj( - "day" -> day, - "month" -> month, - "year" -> year + "day" -> "", + "month" -> "4", + "year" -> "2024" ) ) - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) - when(mockAppConfig.newRevaluedFeature).thenReturn(true) - when(mockServiceInfoService.getPartial(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(customBtaNavigationLinks)) - when(mockDataCacheConnector.fetchAtedRefData[String](ArgumentMatchers.eq(DelegatedClientAtedRefNumber))(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(Some("XN1200000100001"))) - when(mockDataCacheConnector.fetchAndGetFormData[Boolean](ArgumentMatchers.any()) - (ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockBackLinkCacheConnector.saveBackLink(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) - when(mockPropertyDetailsService.saveDraftPropertyDetailsRevalued(ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn(Future.successful(OK)) + setupAuthForOrganisation() + setupCommonMockExpectations(true) val result = testController.save("1", 2015, None).apply(SessionBuilder.updateRequestWithSession(FakeRequest().withJsonBody(inputJson), userId)) status(result) mustBe BAD_REQUEST contentAsString(result) must include("There is a problem") } } + "redirect to home page" when { - "newRevaluedFeature flag is set to false" in new Setup { - val authMock = authResultDefault(AffinityGroup.Organisation, defaultEnrolmentSet) - setAuthMocks(authMock) + "newRevaluedFeature flag is set to false" in { + setupAuthForOrganisation() when(mockAppConfig.newRevaluedFeature).thenReturn(false) val result = testController.view("1").apply(SessionBuilder.buildRequestWithSession(userId)) status(result) mustBe SEE_OTHER @@ -242,4 +180,7 @@ class PropertyDetailsDateOfRevalueControllerSpec extends PlaySpec with GuiceOneS } } + } + + diff --git a/test/controllers/propertyDetails/PropertyDetailsTestFixture.scala b/test/controllers/propertyDetails/PropertyDetailsTestFixture.scala new file mode 100644 index 00000000..c44553de --- /dev/null +++ b/test/controllers/propertyDetails/PropertyDetailsTestFixture.scala @@ -0,0 +1,135 @@ +/* + * 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.propertyDetails + +import builders.PropertyDetailsBuilder +import config.ApplicationConfig +import connectors.{BackLinkCacheConnector, DataCacheConnector} +import controllers.auth.AuthAction +import models.{DateOfChange, HasBeenRevalued, PropertyDetailsNewValuation, PropertyDetailsRevalued} +import org.mockito.ArgumentMatchers.{any, eq => eqs} +import org.mockito.Mockito.{verify, when} +import org.scalatestplus.play.PlaySpec +import org.scalatestplus.play.guice.GuiceOneServerPerSuite +import play.api.http.Status.OK +import play.api.i18n.{Lang, MessagesApi, MessagesImpl} +import play.api.mvc.MessagesControllerComponents +import services.{PropertyDetailsCacheSuccessResponse, PropertyDetailsService, ServiceInfoService} +import testhelpers.MockAuthUtil +import uk.gov.hmrc.auth.core.{AffinityGroup, Enrolment} +import uk.gov.hmrc.http.HeaderCarrier +import utils.AtedConstants.{DelegatedClientAtedRefNumber, FortyThousandValueDateOfChange, HasPropertyBeenRevalued, propertyDetailsNewValuationValue} +import views.html.BtaNavigationLinks +import views.html.propertyDetails.propertyDetailsDateOfRevalue + +import java.time.LocalDate +import scala.concurrent.Future + +abstract class PropertyDetailsTestFixture extends PlaySpec with GuiceOneServerPerSuite with MockAuthUtil { + + + implicit val mockAppConfig: ApplicationConfig = mock[ApplicationConfig] + implicit lazy val hc: HeaderCarrier = HeaderCarrier() + val mockMcc: MessagesControllerComponents = app.injector.instanceOf[MessagesControllerComponents] + val mockPropertyDetailsService: PropertyDetailsService = mock[PropertyDetailsService] + val mockDataCacheConnector: DataCacheConnector = mock[DataCacheConnector] + val mockBackLinkCacheConnector: BackLinkCacheConnector = mock[BackLinkCacheConnector] + val mockNewValuationController: PropertyDetailsNewValuationController = mock[PropertyDetailsNewValuationController] + val mockIsFullTaxPeriodController: IsFullTaxPeriodController = mock[IsFullTaxPeriodController] + lazy implicit val messages: MessagesImpl = MessagesImpl(Lang("en-GB"), messagesApi) + val messagesApi: MessagesApi = app.injector.instanceOf[MessagesApi] + val btaNavigationLinksView: BtaNavigationLinks = app.injector.instanceOf[BtaNavigationLinks] + val mockServiceInfoService: ServiceInfoService = mock[ServiceInfoService] + val injectedViewInstance: propertyDetailsDateOfRevalue = app.injector.instanceOf[views.html.propertyDetails.propertyDetailsDateOfRevalue] + val mockAuthAction: AuthAction = new AuthAction( + mockAppConfig, + mockDelegationService, + mockAuthConnector + ) + val testController: PropertyDetailsDateOfRevalueController = new PropertyDetailsDateOfRevalueController( + mockMcc, + mockAuthAction, + mockServiceInfoService, + injectedViewInstance, + mockPropertyDetailsService, + mockBackLinkCacheConnector, + mockDataCacheConnector, + mockIsFullTaxPeriodController + ) + + def setupAuthForOrganisation(enrolmentSet: Set[Enrolment] = defaultEnrolmentSet) = { + val authMock = authResultDefault(AffinityGroup.Organisation, enrolmentSet) + enrolmentSet match { + case set if set == invalidEnrolmentSet => setInvalidAuthMocks(authMock) + case _ => setAuthMocks(authMock) + } + } + + def setupDataCacheConnectorExpectations(newValuation: Some[BigDecimal], hasPropertyBeenRevalued: Some[Boolean], dateOfRevaluationChange: Some[LocalDate]) = { + when(mockDataCacheConnector.fetchAndGetFormData[HasBeenRevalued](eqs(HasPropertyBeenRevalued))(any(), any())).thenReturn(Future.successful(Some(HasBeenRevalued(hasPropertyBeenRevalued)))) + + + when(mockDataCacheConnector.fetchAndGetFormData[PropertyDetailsNewValuation](eqs(propertyDetailsNewValuationValue)) + (any(), any())) + .thenReturn(Future.successful(Some(PropertyDetailsNewValuation(newValuation)))) + + when(mockDataCacheConnector.fetchAndGetFormData[DateOfChange](eqs(FortyThousandValueDateOfChange)) + (any(), any())) + .thenReturn(Future.successful(Some(DateOfChange(dateOfRevaluationChange)))) + } + + def setupCommonMockExpectations(isFeatureFlagEnabled: Boolean) = { + val customBtaNavigationLinks = btaNavigationLinksView()(messages, mockAppConfig) + when(mockAppConfig.newRevaluedFeature).thenReturn(isFeatureFlagEnabled) + when(mockServiceInfoService.getPartial(any(), any(), any())).thenReturn(Future.successful(customBtaNavigationLinks)) + when(mockDataCacheConnector.fetchAtedRefData[String](eqs(DelegatedClientAtedRefNumber))(any(), any())).thenReturn(Future.successful(Some("XN1200000100001"))) + when(mockDataCacheConnector.fetchAndGetFormData[Boolean](any()) + (any(), any())).thenReturn(Future.successful(None)) + when(mockBackLinkCacheConnector.fetchAndGetBackLink(any())(any())).thenReturn(Future.successful(None)) + when(mockBackLinkCacheConnector.saveBackLink(any(), any())(any())).thenReturn(Future.successful(None)) + + } + + def setupPropertyDetailServiceMockExpectations() = { + val propertyDetails = PropertyDetailsBuilder.getPropertyDetails("1", Some("z11 1zz")).copy(value = None) + when(mockPropertyDetailsService.retrieveDraftPropertyDetails(any())(any(), any())) + .thenReturn(Future.successful(PropertyDetailsCacheSuccessResponse(propertyDetails))) + when(mockPropertyDetailsService.saveDraftPropertyDetailsRevalued(any(), any())(any(), any())).thenReturn(Future.successful(OK)) + + } + + def verifySaveBackLinkIsCalled = { + verify(mockBackLinkCacheConnector).saveBackLink(any(), any())(any()) + } + + def verifyDataCacheConnectorRetursHasBeenRevalued(revalued: String) = { + verify(mockDataCacheConnector).fetchAndGetFormData[HasBeenRevalued]( + eqs(revalued) + )(any(), any()) + } + + def verifyPropertyDetailsService(isPropertyRevalued: Option[Boolean], revaluedValue: Option[BigDecimal], revaluedDate: Option[LocalDate], partAcqDispDate: Option[LocalDate]) = { + val expectedPropertyDetails = PropertyDetailsRevalued( + isPropertyRevalued = isPropertyRevalued, + revaluedValue = revaluedValue, + revaluedDate = revaluedDate, + partAcqDispDate = partAcqDispDate + ) + verify(mockPropertyDetailsService).saveDraftPropertyDetailsRevalued(any(), eqs(expectedPropertyDetails))(any(), any()) + } + +} diff --git a/test/testhelpers/MockAuthUtil.scala b/test/testhelpers/MockAuthUtil.scala index b98c1171..6310b85b 100644 --- a/test/testhelpers/MockAuthUtil.scala +++ b/test/testhelpers/MockAuthUtil.scala @@ -16,8 +16,6 @@ package testhelpers -import java.util.UUID - import models.{DelegationModel, StandardAuthRetrievals} import org.mockito.ArgumentMatchers import org.mockito.Mockito.when @@ -31,10 +29,10 @@ import scala.concurrent.Future trait MockAuthUtil extends MockitoSugar with TestUtil { - lazy val userId = s"user-${UUID.randomUUID}" - lazy val mockAuthConnector: PlayAuthConnector = mock[PlayAuthConnector] - lazy val mockDelegationModel: DelegationModel = mock[DelegationModel] - lazy val mockDelegationService: DelegationService = mock[DelegationService] + lazy val userId = "testUserId" + lazy val mockAuthConnector: PlayAuthConnector = mock[PlayAuthConnector] + lazy val mockDelegationModel: DelegationModel = mock[DelegationModel] + lazy val mockDelegationService: DelegationService = mock[DelegationService] val agentStandardRetrievals: StandardAuthRetrievals = StandardAuthRetrievals(agentEnrolmentSet, Some(agentAffinity), Some(delegationModel)) val organisationStandardRetrievals: StandardAuthRetrievals = StandardAuthRetrievals(defaultEnrolmentSet, Some(organisationAffinity), Some(delegationModel)) @@ -42,28 +40,28 @@ trait MockAuthUtil extends MockitoSugar with TestUtil { def authResultDefault(affinityGroup: AffinityGroup, enrolments: Set[Enrolment]): Enrolments ~ Some[AffinityGroup] ~ Some[String] = { - new ~( - new ~( - Enrolments(enrolments), - Some(affinityGroup) - ), + new~( + new~( + Enrolments(enrolments), + Some(affinityGroup) + ), Some(internalId) ) } def setAuthMocks( - authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] - ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { + authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] + ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { when(mockDelegationService.delegationCall(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(Some(delegationModel))) when(mockAuthConnector.authorise[Enrolments ~ Some[AffinityGroup] ~ Some[String]] - (ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())) - .thenReturn(Future.successful(authResult)) + (ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())) + .thenReturn(Future.successful(authResult)) } def noDelegationModelAuthMocks( - authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] - ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { + authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] + ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { when(mockDelegationService.delegationCall(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) when(mockAuthConnector.authorise[Enrolments ~ Some[AffinityGroup] ~ Some[String]] (ArgumentMatchers.any(), ArgumentMatchers.any())(ArgumentMatchers.any(), ArgumentMatchers.any())) @@ -71,8 +69,8 @@ trait MockAuthUtil extends MockitoSugar with TestUtil { } def setInvalidAuthMocks( - authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] - ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { + authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] + ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { when(mockDelegationService.delegationCall(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(Some(delegationModel))) when(mockAuthConnector.authorise[Enrolments ~ Some[AffinityGroup] ~ Some[String]] @@ -81,8 +79,8 @@ trait MockAuthUtil extends MockitoSugar with TestUtil { } def setForbiddenAuthMocks( - authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] - ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { + authResult: Enrolments ~ Some[AffinityGroup] ~ Some[String] + ): OngoingStubbing[Future[Enrolments ~ Some[AffinityGroup] ~ Some[String]]] = { when(mockDelegationService.delegationCall(ArgumentMatchers.any())(ArgumentMatchers.any())).thenReturn(Future.successful(None)) when(mockAuthConnector.authorise[Enrolments ~ Some[AffinityGroup] ~ Some[String]]