Skip to content

Commit

Permalink
Merge pull request #51 from hmrc/ukims-validation
Browse files Browse the repository at this point in the history
UKIMS form validation
  • Loading branch information
Ewan-James-Donovan authored May 13, 2024
2 parents c4ca1a6 + 42e2456 commit 561eecb
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 30 deletions.
8 changes: 5 additions & 3 deletions app/forms/UkimsNumberFormProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@
package forms

import javax.inject.Inject

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

class UkimsNumberFormProvider @Inject() extends Mappings {

def apply(): Form[String] =
Form(
"value" -> text("ukimsNumber.error.required")
.verifying(maxLength(100, "ukimsNumber.error.length"))
.transform(removeWhitespace, identity[String])
.verifying(regexp(StringFieldRegex.ukimsNumberRegex, "ukimsNumber.error.invalidFormat"))
)
}
}
2 changes: 1 addition & 1 deletion app/forms/mappings/helpers/RemoveWhitespace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ object RemoveWhitespace {

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

}
}
22 changes: 22 additions & 0 deletions app/models/StringFieldRegex.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 models

object StringFieldRegex {
val ukimsNumberRegex: String = "^(GB|XI)[0-9]{12}[0-9]{14}$"

}
2 changes: 1 addition & 1 deletion conf/messages.en
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ ukimsNumber.heading = What is your UKIMS number?
ukimsNumber.hint = For example, XI47699357400020231115081800
ukimsNumber.linkText = I am not UKIMS registered
ukimsNumber.error.required = Enter your UKIMS number
ukimsNumber.error.length = UkimsNumber must be 100 characters or less
ukimsNumber.error.invalidFormat = Enter your UKIMS number in the correct format
ukimsNumber.checkYourAnswersLabel = UKIMS Number
ukimsNumber.change.hidden = UKIMS Number

Expand Down
2 changes: 1 addition & 1 deletion test/controllers/UkimsNumberControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class UkimsNumberControllerSpec extends SpecBase with MockitoSugar {
running(application) {
val request =
FakeRequest(POST, ukimsNumberRoute)
.withFormUrlEncodedBody(("value", "answer"))
.withFormUrlEncodedBody(("value", "XI47699357400020231115081800"))

val result = route(application, request).value

Expand Down
138 changes: 115 additions & 23 deletions test/forms/UkimsNumberFormProviderSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,129 @@
package forms

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

class UkimsNumberFormProviderSpec extends StringFieldBehaviours {

val requiredKey = "ukimsNumber.error.required"
val lengthKey = "ukimsNumber.error.length"
val maxLength = 100
private val formProvider = new UkimsNumberFormProvider()
private val form: Form[String] = formProvider()
private val requiredKey = "ukimsNumber.error.required"
private val invalidFormatKey = "ukimsNumber.error.invalidFormat"
private val fieldName = "value"

val form = new UkimsNumberFormProvider()()
".ukimsNumber" - {

".value" - {
"valid UKIMS number" - {

val fieldName = "value"
val ukimsNumberGenerator: Gen[String] = {
val prefixGen = Gen.oneOf("GB", "XI")
val firstDigitsGen = Gen.listOfN(12, Gen.numChar).map(_.mkString)
val lastDigitsGen = Gen.listOfN(14, Gen.numChar).map(_.mkString)

behave like fieldThatBindsValidData(
form,
fieldName,
stringsWithMaxLength(maxLength)
)
for {
prefix <- prefixGen
firstDigits <- firstDigitsGen
lastDigits <- lastDigitsGen
} yield s"$prefix$firstDigits$lastDigits"
}

behave like fieldWithMaxLength(
form,
fieldName,
maxLength = maxLength,
lengthError = FormError(fieldName, lengthKey, Seq(maxLength))
)
behave like mandatoryField(form, fieldName, requiredError = FormError(fieldName, requiredKey))

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

}

"valid UKIMS number with spaces" - {

val ukimsNumberGenerator: Gen[String] = {
val prefixGen = Gen.oneOf("GB", "XI")
val firstDigitsGen = Gen.listOfN(12, Gen.numChar).map(_.mkString)
val lastDigitsGen = Gen.listOfN(14, Gen.numChar).map(_.mkString)

for {
prefix <- prefixGen
firstDigits <- firstDigitsGen
lastDigits <- lastDigitsGen
} yield s"$prefix $firstDigits $lastDigits"
}

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

behave like fieldThatBindsValidData(form, fieldName, ukimsNumberGenerator)

}

"invalid UKIMS number" - {

"invalid UKIMS number with invalid length" - {

val invalidUkimsNumberGeneratorWithInvalidLength: Gen[String] = {

val prefixGen = Gen.oneOf("GB", "XI")
val firstDigitsGen = Gen.listOfN(12, Gen.numChar).map(_.mkString)
val lastDigitsGen = Gen.listOfN(15, Gen.numChar).map(_.mkString)

for {
prefix <- prefixGen
firstDigits <- firstDigitsGen
lastDigits <- lastDigitsGen
} yield s"$prefix$firstDigits$lastDigits"
}

behave like fieldThatErrorsOnInvalidData(
form,
fieldName,
invalidUkimsNumberGeneratorWithInvalidLength,
FormError(fieldName, invalidFormatKey)
)
}

"invalid UKIMS number with invalid prefix" - {

val invalidUkimsNumberGeneratorWithInvalidPrefix: Gen[String] = {
val prefixGen = Gen.oneOf("AA", "BB")
val firstDigitsGen = Gen.listOfN(12, Gen.numChar).map(_.mkString)
val lastDigitsGen = Gen.listOfN(14, Gen.numChar).map(_.mkString)

for {
prefix <- prefixGen
firstDigits <- firstDigitsGen
lastDigits <- lastDigitsGen
} yield s"$prefix$firstDigits$lastDigits"
}

behave like fieldThatErrorsOnInvalidData(
form,
fieldName,
invalidUkimsNumberGeneratorWithInvalidPrefix,
FormError(fieldName, invalidFormatKey)
)

}

"invalid UKIMS number with special characters" - {

val invalidUkimsNumberGeneratorWithSpecialCharacters: Gen[String] = {
val prefixGen = Gen.oneOf(" ", "A-", "B_")
val firstDigitsGen = Gen.listOfN(12, Gen.numChar).map(_.mkString)
val lastDigitsGen = Gen.listOfN(14, Gen.numChar).map(_.mkString)

for {
prefix <- prefixGen
firstDigits <- firstDigitsGen
lastDigits <- lastDigitsGen
} yield s"$prefix$firstDigits$lastDigits"
}

behave like fieldThatErrorsOnInvalidData(
form,
fieldName,
invalidUkimsNumberGeneratorWithSpecialCharacters,
FormError(fieldName, invalidFormatKey)
)

}
}
}
}
2 changes: 1 addition & 1 deletion test/forms/behaviours/FieldBehaviours.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ trait FieldBehaviours extends FormSpec with ScalaCheckPropertyChecks with Genera
result.errors.head.message mustBe invalidError.message
}
}
}
}

0 comments on commit 561eecb

Please sign in to comment.