Skip to content

Commit

Permalink
Merge pull request #48 from hmrc/nirms-validation
Browse files Browse the repository at this point in the history
Nirms Validation + Tests
  • Loading branch information
Ewan-James-Donovan authored May 13, 2024
2 parents 2525ef8 + adf34a8 commit 930ad8e
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 41 deletions.
5 changes: 3 additions & 2 deletions app/forms/NirmsNumberFormProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
package forms

import javax.inject.Inject

import forms.mappings.Mappings
import forms.mappings.helpers.RemoveWhitespace.removeWhitespace
import play.api.data.Form

class NirmsNumberFormProvider @Inject() extends Mappings {

def apply(): Form[String] =
Form(
"value" -> text("nirmsNumber.error.required")
.verifying(maxLength(100, "nirmsNumber.error.length"))
.transform(removeWhitespace, identity[String])
.verifying(regexp("RMS-?(GB|NI)-?[0-9]{6}", "nirmsNumber.error.invalidFormat"))
)
}
23 changes: 23 additions & 0 deletions app/forms/mappings/helpers/RemoveWhitespace.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 forms.mappings.helpers

object RemoveWhitespace {

def removeWhitespace: String => String = _.filterNot(_.isWhitespace)

}
2 changes: 1 addition & 1 deletion app/views/NirmsNumberView.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

@govukInput(
InputViewModel(
field = form("nirmsNumber"),
field = form("value"),
label = LabelViewModel(messages("nirmsNumber.heading")).asPageHeading(Large)
).withHint(Hint(content = Text(messages("nirmsNumber.hint"))))
.withWidth(Fixed10)
Expand Down
2 changes: 1 addition & 1 deletion test/controllers/NirmsNumberControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class NirmsNumberControllerSpec extends SpecBase with MockitoSugar {
running(application) {
val request =
FakeRequest(POST, nirmsNumberRoute)
.withFormUrlEncodedBody(("value", "answer"))
.withFormUrlEncodedBody(("value", "RMS-GB-123456"))

val result = route(application, request).value

Expand Down
58 changes: 35 additions & 23 deletions test/forms/NirmsNumberFormProviderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,49 @@
package forms

import forms.behaviours.StringFieldBehaviours
import play.api.data.FormError
import org.scalacheck.Gen
import play.api.data.{Form, FormError}

class NirmsNumberFormProviderSpec extends StringFieldBehaviours {
private val formProvider = new NirmsNumberFormProvider()
private val form: Form[String] = formProvider()
private val requiredKey = "nirmsNumber.error.required"
private val invalidKey = "nirmsNumber.error.invalidFormat"

val requiredKey = "nirmsNumber.error.required"
val lengthKey = "nirmsNumber.error.length"
val maxLength = 100
val nirmsNumberGenerator: Gen[String] = {
val regionGen = Gen.oneOf("GB", "NI")
val digitsGen = Gen.listOfN(6, Gen.numChar).map(_.mkString)
val hyphenGen = Gen.oneOf("", "-")

val form = new NirmsNumberFormProvider()()
for {
region <- regionGen
digits <- digitsGen
hyphen1 <- hyphenGen
hyphen2 <- hyphenGen
} yield s"RMS$hyphen1$region$hyphen2$digits"
}

val nonNirmsNumberGenerator: Gen[String] = {
val invalidRegionGen = Gen.alphaStr.suchThat(s => s != "GB" && s != "NI" && s.nonEmpty)
val invalidDigitsGen = for {
length <- Gen.choose(1, 10)
digits <- Gen.listOfN(length, Gen.oneOf(Gen.alphaChar, Gen.numChar))
} yield digits.mkString

Gen.oneOf(
invalidRegionGen.map(region => s"RMS-$region-123456"),
invalidDigitsGen.map(digits => s"RMS-GB-$digits")
)
}

".value" - {
".nirmsNumber" - {

val fieldName = "value"

behave like fieldThatBindsValidData(
form,
fieldName,
stringsWithMaxLength(maxLength)
)
behave like mandatoryField(form, fieldName, requiredError = FormError(fieldName, requiredKey))

behave like fieldWithMaxLength(
form,
fieldName,
maxLength = maxLength,
lengthError = FormError(fieldName, lengthKey, Seq(maxLength))
)
behave like fieldThatBindsValidData(form, fieldName, nirmsNumberGenerator)

behave like mandatoryField(
form,
fieldName,
requiredError = FormError(fieldName, requiredKey)
)
behave like fieldThatErrorsOnInvalidData(form, fieldName, nonNirmsNumberGenerator, FormError(fieldName, invalidKey))
}
}
}
35 changes: 21 additions & 14 deletions test/forms/behaviours/FieldBehaviours.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,17 @@ import play.api.data.{Form, FormError}

trait FieldBehaviours extends FormSpec with ScalaCheckPropertyChecks with Generators {

def fieldThatBindsValidData(form: Form[_],
fieldName: String,
validDataGenerator: Gen[String]): Unit = {

def fieldThatBindsValidData(form: Form[_], fieldName: String, validDataGenerator: Gen[String]): Unit =
"bind valid data" in {

forAll(validDataGenerator -> "validDataItem") {
dataItem: String =>
val result = form.bind(Map(fieldName -> dataItem)).apply(fieldName)
result.value.value mustBe dataItem
result.errors mustBe empty
forAll(validDataGenerator -> "validDataItem") { dataItem: String =>
val result = form.bind(Map(fieldName -> dataItem)).apply(fieldName)
result.value.value mustBe dataItem
result.errors mustBe empty
}
}
}

def mandatoryField(form: Form[_],
fieldName: String,
requiredError: FormError): Unit = {
def mandatoryField(form: Form[_], fieldName: String, requiredError: FormError): Unit = {

"not bind when key is not present at all" in {

Expand All @@ -55,4 +48,18 @@ trait FieldBehaviours extends FormSpec with ScalaCheckPropertyChecks with Genera
result.errors mustEqual Seq(requiredError)
}
}
}

def fieldThatErrorsOnInvalidData(
form: Form[_],
fieldName: String,
invalidDataGenerator: Gen[String],
invalidError: FormError
): Unit =
"error on invalid data" in {
forAll(invalidDataGenerator -> "invalidDataItem") { dataItem: String =>
val result = form.bind(Map(fieldName -> dataItem)).apply(fieldName)
result.errors.size mustBe 1
result.errors.head.message mustBe invalidError.message
}
}
}

0 comments on commit 930ad8e

Please sign in to comment.