Skip to content

Commit

Permalink
PLATUI 2972 METATEST (#300)
Browse files Browse the repository at this point in the history
* add meta-tests that check all components have unit / integration tests
* exclude test fixtures for GovukPasswordInput (not yet implemented) and HMRC accessible-autocomplete helper
* add missing integration tests for GovukHeader, HmrcFooter, HmrcReportTechnicalIssue
* remove redundant assets config
  • Loading branch information
ellamdav committed Apr 24, 2024
1 parent 4221727 commit ee5ee7f
Show file tree
Hide file tree
Showing 107 changed files with 588 additions and 39 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
For compatibility information see `govukFrontendVersion` and `hmrcFrontendVersion` in
[LibDependencies](project/LibDependencies.scala)

## [9.10.0] - 2024-04-24

### Changed

- Added meta-tests to ensure fixture-driven unit tests and Scalacheck-driven integration tests cover all components
- Fixed up existing gaps in coverage highlighted by these new tests

### Compatible with

- [hmrc/hmrc-frontend v6.17.0](https://github.com/hmrc/hmrc-frontend/releases/tag/v6.17.0)
- [alphagov/govuk-frontend v5.3.0](https://github.com/alphagov/govuk-frontend/releases/tag/v5.3.0)

## [9.9.0] - 2024-04-24

### Changed
Expand Down
11 changes: 6 additions & 5 deletions docs/maintainers/upgrading.md
Expand Up @@ -126,14 +126,15 @@ index 51d2d346..713db75d 100644
### Comparing forked components in other repos
As noted above, some of our `play-frontend-hmrc` components are not direct ports, but are manually created and need to be kept manually aligned with `govuk-frontend` in particular.

For example, if there are changs to the `GovukCookieBanner` template or styles, these should be compared against the cookie banner in `tracking-consent-frontend` (see [banner.ts](https://github.com/hmrc/tracking-consent-frontend/blob/main/js/src/ui/banner.ts)).
For example, if there are changes to the `GovukCookieBanner` template or styles, these should be compared against the cookie banner in `tracking-consent-frontend` (see [banner.ts](https://github.com/hmrc/tracking-consent-frontend/blob/main/js/src/ui/banner.ts)).

#### Adding New Components
When running the above steps, there will be test failures if existing components have changed. However, there will be no
failures for new components which have been added to `hmrc-frontend` or `govuk-frontend` but which have not yet been implemented in
`play-frontend-hmrc`.
When running the above steps, there will be test failures if existing components have changed.
Any new components which have been added to `hmrc-frontend` or `govuk-frontend` but which have not yet been implemented in
`play-frontend-hmrc` should also get flagged by the [TemplateUnitBaseMetaSpec](/play-frontend-hmrc-play-30/src/test/scala/uk/gov/hmrc/helpers/views/TemplateUnitBaseMetaSpec.scala)-
and [TemplateIntegrationBaseMetaSpec](/it-play-30/src/test/scala/uk/gov/hmrc/support/TemplateIntegrationBaseMetaSpec.scala)-derived meta-tests for each underlying library.

Therefore, it is important to look at the diffs between versions of `govuk-frontend`, and read the CHANGELOG.
That said, it is still important to look at the diffs between versions of `govuk-frontend`, and read the CHANGELOG.

To add a new component:
- Add the view model as a Scala case class in the folder: `src/main/scala/uk/gov/hmrc/(hmrc|govuk)frontend/views/viewmodels`
Expand Down
@@ -0,0 +1,25 @@
/*
* Copyright 2023 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.govukfrontend.support

import uk.gov.hmrc.support.TemplateIntegrationBaseMetaSpec

class TemplateIntegrationMetaSpec
extends TemplateIntegrationBaseMetaSpec(
libraryName = "govuk-frontend",
ignoredHelpers = Seq("govukTemplate", "govukLayout")
)
@@ -0,0 +1,25 @@
/*
* Copyright 2019 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.govukfrontend.views.components

import uk.gov.hmrc.govukfrontend.support.TemplateIntegrationSpec
import uk.gov.hmrc.govukfrontend.views.html.components._
import uk.gov.hmrc.govukfrontend.views.viewmodels.header.Header
import uk.gov.hmrc.govukfrontend.views.viewmodels.header.Generators._

object GovukHeaderIntegrationSpec
extends TemplateIntegrationSpec[Header, GovukHeader](govukComponentName = "govukHeader")
@@ -0,0 +1,55 @@
/*
* Copyright 2023 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.hmrcfrontend.support

import org.scalacheck.Arbitrary
import play.api.i18n.Messages
import play.api.libs.json.OWrites
import play.twirl.api.{HtmlFormat, Template2}
import uk.gov.hmrc.hmrcfrontend.views.HmrcFrontendDependency.hmrcFrontendVersion
import uk.gov.hmrc.helpers.MessagesSupport
import uk.gov.hmrc.support.TemplateIntegrationBaseSpec

import scala.reflect.ClassTag
import scala.util.Try

/**
* Base class for integration testing a Twirl template against the Nunjucks template rendering service,
* where the template takes a viewmodel plus an implicit Messages API
*
* @tparam T Type representing the input parameters of the Twirl template
*/
abstract class MessagesAwareTemplateIntegrationSpec[T: OWrites: Arbitrary, C <: Template2[
T,
Messages,
HtmlFormat.Appendable
]: ClassTag](
hmrcComponentName: String,
seed: Option[String] = None
) extends TemplateIntegrationBaseSpec[T](hmrcComponentName, seed)
with MessagesSupport {

protected val libraryName: String = "hmrc"

protected val libraryVersion: String = hmrcFrontendVersion

private val component: C = app.injector.instanceOf[C]

def render(templateParams: T): Try[HtmlFormat.Appendable] =
Try(component.render(templateParams, implicitly))

}
@@ -0,0 +1,22 @@
/*
* Copyright 2023 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.hmrcfrontend.support

import uk.gov.hmrc.support.TemplateIntegrationBaseMetaSpec


class TemplateIntegrationMetaSpec extends TemplateIntegrationBaseMetaSpec("hmrc-frontend")
Expand Up @@ -16,29 +16,11 @@

package uk.gov.hmrc.hmrcfrontend.views.components

import play.twirl.api.HtmlFormat
import uk.gov.hmrc.helpers.MessagesSupport
import uk.gov.hmrc.hmrcfrontend.views.HmrcFrontendDependency.hmrcFrontendVersion
import uk.gov.hmrc.hmrcfrontend.support.MessagesAwareTemplateIntegrationSpec
import uk.gov.hmrc.hmrcfrontend.views.html.components._
import uk.gov.hmrc.hmrcfrontend.views.viewmodels.charactercount.Generators._
import uk.gov.hmrc.support.TemplateIntegrationBaseSpec

import scala.util.Try

object HmrcCharacterCountIntegrationSpec
extends TemplateIntegrationBaseSpec[CharacterCount](
componentName = "hmrcCharacterCount",
seed = None
extends MessagesAwareTemplateIntegrationSpec[CharacterCount, HmrcCharacterCount](
hmrcComponentName = "hmrcCharacterCount"
)
with MessagesSupport {

protected val libraryName: String = "hmrc"

protected val libraryVersion: String = hmrcFrontendVersion

private val component = app.injector.instanceOf[HmrcCharacterCount]

override def render(characterCount: CharacterCount): Try[HtmlFormat.Appendable] =
Try(component(characterCount))

}
@@ -0,0 +1,24 @@
/*
* Copyright 2019 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.hmrcfrontend.views.components

import uk.gov.hmrc.hmrcfrontend.support.MessagesAwareTemplateIntegrationSpec
import uk.gov.hmrc.hmrcfrontend.views.html.components._
import uk.gov.hmrc.hmrcfrontend.views.viewmodels.footer.Generators._

object HmrcFooterIntegrationSpec
extends MessagesAwareTemplateIntegrationSpec[Footer, HmrcFooter](hmrcComponentName = "hmrcFooter")
@@ -0,0 +1,26 @@
/*
* Copyright 2023 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.hmrcfrontend.views.components

import uk.gov.hmrc.hmrcfrontend.support.TemplateIntegrationSpec
import uk.gov.hmrc.hmrcfrontend.views.html.components._
import uk.gov.hmrc.hmrcfrontend.views.viewmodels.reporttechnicalissue.Generators._

object HmrcReportTechnicalIssueIntegrationSpec
extends TemplateIntegrationSpec[ReportTechnicalIssue, HmrcReportTechnicalIssue](
hmrcComponentName = "hmrcReportTechnicalIssue"
)
@@ -0,0 +1,66 @@
/*
* 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 uk.gov.hmrc.support

import better.files.File
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

abstract class TemplateIntegrationBaseMetaSpec(val libraryName: String, val ignoredHelpers: Seq[String] = Seq.empty)
extends AnyWordSpec
with Matchers {

private val libraryDir = libraryName.replace("-", "")
private val libraryPrefix = libraryName.split('-').head

private val itPath = "it-play-30"
private val itRoot = File(itPath)
private val testRoot = itRoot / "src" / "test" / "scala"
private val componentTestDir = testRoot / "uk" / "gov" / "hmrc" / libraryDir / "views" / "components"

private val mainPath = "play-frontend-hmrc-play-30"
private val mainRoot = File(mainPath)
private val templatesRoot = mainRoot / "src" / "main" / "twirl"
private val templatesDir = templatesRoot / "uk" / "gov" / "hmrc" / libraryDir / "views" / "components"

this.getClass.getCanonicalName when {

val templates = templatesDir.children
.filter(_.isRegularFile)
.map(_.name)
.map(filename => filename.split('.').head)
.map(name => s"${name.head.toLower}${name.tail}")
.filter(_.startsWith(libraryPrefix))
.filterNot(ignoredHelpers.contains(_))
.toList
.sorted

templates.foreach { template =>
s"component is $template" should {

"be covered by an integration test" in {
withClue(s"""no test found for component "$template" under $componentTestDir""") {
componentTestDir.children
.filter(_.isRegularFile)
.exists(_.contentAsString.contains(s""""$template"""")) should be(true)
}
}
}
}
}

}
Expand Up @@ -23,12 +23,10 @@ import uk.gov.hmrc.hmrcfrontend.views.HmrcFrontendDependency
class AssetsConfig @Inject() () {
private val hmrcFrontendVersion = HmrcFrontendDependency.hmrcFrontendVersion

lazy val html5ShivJsUrl: String = Assets.at("vendor/html5shiv.min.js").url
lazy val hmrcFrontendCssUrl: String = hmrcFrontendAssetUrl(s"hmrc-frontend-$hmrcFrontendVersion.min.css")
lazy val hmrcFrontendIe8CssUrl: String = hmrcFrontendAssetUrl(s"hmrc-frontend-ie8-$hmrcFrontendVersion.min.css")
lazy val hmrcFrontendJsUrl: String = hmrcFrontendAssetUrl(s"hmrc-frontend-$hmrcFrontendVersion.min.js")
lazy val autocompleteJsUrl: String = hmrcFrontendAssetUrl(s"accessible-autocomplete-$hmrcFrontendVersion.js")
lazy val autocompleteCssUrl: String = hmrcFrontendAssetUrl(s"accessible-autocomplete-$hmrcFrontendVersion.css")
lazy val hmrcFrontendCssUrl: String = hmrcFrontendAssetUrl(s"hmrc-frontend-$hmrcFrontendVersion.min.css")
lazy val hmrcFrontendJsUrl: String = hmrcFrontendAssetUrl(s"hmrc-frontend-$hmrcFrontendVersion.min.js")
lazy val autocompleteJsUrl: String = hmrcFrontendAssetUrl(s"accessible-autocomplete-$hmrcFrontendVersion.js")
lazy val autocompleteCssUrl: String = hmrcFrontendAssetUrl(s"accessible-autocomplete-$hmrcFrontendVersion.css")

private def hmrcFrontendAssetUrl(filename: String) = Assets.at(filename).url
}
Expand Up @@ -30,5 +30,5 @@ case class Footer(

object Footer {

implicit def jsonFormats: Format[Footer] = Json.using[Json.WithDefaultValues].format[Footer]
implicit def jsonFormats: OFormat[Footer] = Json.using[Json.WithDefaultValues].format[Footer]
}
Expand Up @@ -14,16 +14,19 @@
* limitations under the License.
*@

@import uk.gov.hmrc.hmrcfrontend.views.html.components._

@this()


@(params: ReportTechnicalIssue)
@import params._
@defining(if(serviceId.nonEmpty) serviceId else serviceCode) { service =>
<a lang="@params.language.code"
hreflang="@params.language.code"
class="@toClasses("govuk-link hmrc-report-technical-issue ", classes.getOrElse(""))"
@if(params.referrerUrl.nonEmpty) { rel="noreferrer noopener" }
@if(params.referrerUrl.exists(_.nonEmpty)) { rel="noreferrer noopener" }
target="_blank"
href="@params.baseUrl.getOrElse("")/contact/report-technical-problem?newTab=true&amp;service=@urlEncode(service)@if(params.referrerUrl.nonEmpty) {&amp;referrerUrl=@urlEncode(params.referrerUrl.get)}"
href="@params.baseUrl.getOrElse("")/contact/report-technical-problem?newTab=true&amp;service=@urlEncode(service)@params.referrerUrl.filter(_.nonEmpty).map{ url =>&amp;referrerUrl=@urlEncode(url)}"
>@if(params.language.code == "cy") {A yw’r dudalen hon yn gweithio’n iawn? (yn agor tab newydd)} else {Is this page not working properly? (opens in new tab)}</a>
}
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)
@@ -0,0 +1 @@
This fixture is excluded because we decided to not yet implement the Password Input component - see [ADR-0021](docs/maintainers/adr/0021-defer-inclusion-of-password-field.md)

0 comments on commit ee5ee7f

Please sign in to comment.