Skip to content

Commit

Permalink
Created scaffold
Browse files Browse the repository at this point in the history
  • Loading branch information
hmrc-web-operations committed Dec 6, 2022
1 parent a266451 commit 24a2014
Show file tree
Hide file tree
Showing 202 changed files with 8,837 additions and 17 deletions.
56 changes: 56 additions & 0 deletions .g8/checkboxPage/app/controllers/$className$Controller.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package controllers

import controllers.actions._
import forms.$className$FormProvider
import javax.inject.Inject
import models.Mode
import navigation.Navigator
import pages.$className$Page
import play.api.i18n.{I18nSupport, MessagesApi}
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
import repositories.SessionRepository
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController
import views.html.$className$View

import scala.concurrent.{ExecutionContext, Future}

class $className$Controller @Inject()(
override val messagesApi: MessagesApi,
sessionRepository: SessionRepository,
navigator: Navigator,
identify: IdentifierAction,
getData: DataRetrievalAction,
requireData: DataRequiredAction,
formProvider: $className$FormProvider,
val controllerComponents: MessagesControllerComponents,
view: $className$View
)(implicit ec: ExecutionContext) extends FrontendBaseController with I18nSupport {

val form = formProvider()

def onPageLoad(mode: Mode): Action[AnyContent] = (identify andThen getData andThen requireData) {
implicit request =>

val preparedForm = request.userAnswers.get($className$Page) match {
case None => form
case Some(value) => form.fill(value)
}

Ok(view(preparedForm, mode))
}

def onSubmit(mode: Mode): Action[AnyContent] = (identify andThen getData andThen requireData).async {
implicit request =>

form.bindFromRequest().fold(
formWithErrors =>
Future.successful(BadRequest(view(formWithErrors, mode))),

value =>
for {
updatedAnswers <- Future.fromTry(request.userAnswers.set($className$Page, value))
_ <- sessionRepository.set(updatedAnswers)
} yield Redirect(navigator.nextPage($className$Page, mode, updatedAnswers))
)
}
}
16 changes: 16 additions & 0 deletions .g8/checkboxPage/app/forms/$className$FormProvider.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package forms

import javax.inject.Inject

import forms.mappings.Mappings
import play.api.data.Form
import play.api.data.Forms.set
import models.$className$

class $className$FormProvider @Inject() extends Mappings {

def apply(): Form[Set[$className$]] =
Form(
"value" -> set(enumerable[$className$]("$className;format="decap"$.error.required")).verifying(nonEmptySet("$className;format="decap"$.error.required"))
)
}
33 changes: 33 additions & 0 deletions .g8/checkboxPage/app/models/$className$.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package models

import play.api.i18n.Messages
import uk.gov.hmrc.govukfrontend.views.viewmodels.checkboxes.CheckboxItem
import uk.gov.hmrc.govukfrontend.views.viewmodels.content.Text
import viewmodels.govuk.checkbox._

sealed trait $className$

object $className$ extends Enumerable.Implicits {

case object $option1key;format="Camel"$ extends WithName("$option1key;format="decap"$") with $className$
case object $option2key;format="Camel"$ extends WithName("$option2key;format="decap"$") with $className$

val values: Seq[$className$] = Seq(
$option1key;format="Camel"$,
$option2key;format="Camel"$
)

def checkboxItems(implicit messages: Messages): Seq[CheckboxItem] =
values.zipWithIndex.map {
case (value, index) =>
CheckboxItemViewModel(
content = Text(messages(s"$className;format="decap"$.\${value.toString}")),
fieldId = "value",
index = index,
value = value.toString
)
}

implicit val enumerable: Enumerable[$className$] =
Enumerable(values.map(v => v.toString -> v): _*)
}
11 changes: 11 additions & 0 deletions .g8/checkboxPage/app/pages/$className$Page.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pages

import models.$className$
import play.api.libs.json.JsPath

case object $className$Page extends QuestionPage[Set[$className$]] {

override def path: JsPath = JsPath \ toString

override def toString: String = "$className;format="decap"$"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package viewmodels.checkAnswers

import controllers.routes
import models.{CheckMode, UserAnswers}
import pages.$className$Page
import play.api.i18n.Messages
import play.twirl.api.HtmlFormat
import uk.gov.hmrc.govukfrontend.views.viewmodels.content.HtmlContent
import uk.gov.hmrc.govukfrontend.views.viewmodels.summarylist.SummaryListRow
import viewmodels.govuk.summarylist._
import viewmodels.implicits._

object $className$Summary {

def row(answers: UserAnswers)(implicit messages: Messages): Option[SummaryListRow] =
answers.get($className$Page).map {
answers =>

val value = ValueViewModel(
HtmlContent(
answers.map {
answer => HtmlFormat.escape(messages(s"$className;format="decap"$.\$answer")).toString
}
.mkString(",<br>")
)
)
SummaryListRowViewModel(
key = "$className;format="decap"$.checkYourAnswersLabel",
value = value,
actions = Seq(
ActionItemViewModel("site.change", routes.$className$Controller.onPageLoad(CheckMode).url)
.withVisuallyHiddenText(messages("$className;format="decap"$.change.hidden"))
)
)
}
}
32 changes: 32 additions & 0 deletions .g8/checkboxPage/app/views/$className$View.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@this(
layout: templates.Layout,
formHelper: FormWithCSRF,
govukErrorSummary: GovukErrorSummary,
govukCheckboxes: GovukCheckboxes,
govukButton: GovukButton
)

@(form: Form[_], mode: Mode)(implicit request: Request[_], messages: Messages)

@layout(pageTitle = title(form, messages("$className;format="decap"$.title"))) {

@formHelper(action = routes.$className$Controller.onSubmit(mode), 'autoComplete -> "off") {

@if(form.errors.nonEmpty) {
@govukErrorSummary(ErrorSummaryViewModel(form, errorLinkOverrides = Map("value" -> "value_0")))
}

@govukCheckboxes(
CheckboxesViewModel(
form = form,
name = "value",
legend = LegendViewModel(messages("$className;format="decap"$.heading")).asPageHeading(),
items = $className$.checkboxItems
)
)

@govukButton(
ButtonViewModel(messages("site.continue"))
)
}
}
7 changes: 7 additions & 0 deletions .g8/checkboxPage/default.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
description = Generates a controller and view for a page with a set of checkboxes
className = CheckBoxPageName
title = $className;format="decap"$
option1key = option1
option1msg = Option 1
option2key = option2
option2msg = Option 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package controllers

import base.SpecBase
import forms.$className$FormProvider
import models.{NormalMode, $className$, UserAnswers}
import navigation.{FakeNavigator, Navigator}
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.when
import org.scalatestplus.mockito.MockitoSugar
import pages.$className$Page
import play.api.inject.bind
import play.api.mvc.Call
import play.api.test.FakeRequest
import play.api.test.Helpers._
import repositories.SessionRepository
import views.html.$className$View

import scala.concurrent.Future

class $className$ControllerSpec extends SpecBase with MockitoSugar {

def onwardRoute = Call("GET", "/foo")

lazy val $className;format="decap"$Route = routes.$className$Controller.onPageLoad(NormalMode).url

val formProvider = new $className$FormProvider()
val form = formProvider()

"$className$ 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, $className;format="decap"$Route)

val result = route(application, request).value

val view = application.injector.instanceOf[$className$View]

status(result) mustEqual OK

contentAsString(result) mustEqual view(form, NormalMode)(request, messages(application)).toString
}
}

"must populate the view correctly on a GET when the question has previously been answered" in {

val userAnswers = UserAnswers(userAnswersId).set($className$Page, $className$.values.toSet).success.value

val application = applicationBuilder(userAnswers = Some(userAnswers)).build()

running(application) {
val request = FakeRequest(GET, $className;format="decap"$Route)

val view = application.injector.instanceOf[$className$View]

val result = route(application, request).value

status(result) mustEqual OK
contentAsString(result) mustEqual view(form.fill($className$.values.toSet), NormalMode)(request, messages(application)).toString
}
}

"must redirect to the next page when valid data is submitted" in {

val mockSessionRepository = mock[SessionRepository]

when(mockSessionRepository.set(any())) thenReturn Future.successful(true)

val application =
applicationBuilder(userAnswers = Some(emptyUserAnswers))
.overrides(
bind[Navigator].toInstance(new FakeNavigator(onwardRoute)),
bind[SessionRepository].toInstance(mockSessionRepository)
)
.build()

running(application) {
val request =
FakeRequest(POST, $className;format="decap"$Route)
.withFormUrlEncodedBody(("value[0]", $className$.values.head.toString))

val result = route(application, request).value

status(result) mustEqual SEE_OTHER
redirectLocation(result).value mustEqual onwardRoute.url
}
}

"must return a Bad Request and errors when invalid data is submitted" in {

val application = applicationBuilder(userAnswers = Some(emptyUserAnswers)).build()

running(application) {
val request =
FakeRequest(POST, $className;format="decap"$Route)
.withFormUrlEncodedBody(("value", "invalid value"))

val boundForm = form.bind(Map("value" -> "invalid value"))

val view = application.injector.instanceOf[$className$View]

val result = route(application, request).value

status(result) mustEqual BAD_REQUEST
contentAsString(result) mustEqual view(boundForm, NormalMode)(request, messages(application)).toString
}
}

"must redirect to Journey Recovery for a GET if no existing data is found" in {

val application = applicationBuilder(userAnswers = None).build()

running(application) {
val request = FakeRequest(GET, $className;format="decap"$Route)

val result = route(application, request).value

status(result) mustEqual SEE_OTHER
redirectLocation(result).value mustEqual routes.JourneyRecoveryController.onPageLoad().url
}
}

"must redirect to Journey Recovery for a POST if no existing data is found" in {

val application = applicationBuilder(userAnswers = None).build()

running(application) {
val request =
FakeRequest(POST, $className;format="decap"$Route)
.withFormUrlEncodedBody(("value[0]", $className$.values.head.toString))

val result = route(application, request).value

status(result) mustEqual SEE_OTHER
redirectLocation(result).value mustEqual routes.JourneyRecoveryController.onPageLoad().url
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package forms

import forms.behaviours.CheckboxFieldBehaviours
import models.$className$
import play.api.data.FormError

class $className$FormProviderSpec extends CheckboxFieldBehaviours {

val form = new $className$FormProvider()()

".value" - {

val fieldName = "value"
val requiredKey = "$className;format="decap"$.error.required"

behave like checkboxField[$className$](
form,
fieldName,
validValues = $className$.values,
invalidError = FormError(s"\$fieldName[0]", "error.invalid")
)

behave like mandatoryCheckboxField(
form,
fieldName,
requiredKey
)
}
}
Loading

0 comments on commit 24a2014

Please sign in to comment.