diff --git a/app/uk/gov/hmrc/ups/model/PulledItem.scala b/app/uk/gov/hmrc/ups/model/PulledItem.scala index 189a794..29186ec 100644 --- a/app/uk/gov/hmrc/ups/model/PulledItem.scala +++ b/app/uk/gov/hmrc/ups/model/PulledItem.scala @@ -21,7 +21,6 @@ import uk.gov.hmrc.ups.utils.DateFormats import java.time.Instant -// $COVERAGE-OFF$Soon to be deleted case class PulledItem(entityId: EntityId, paperless: Boolean, updatedAt: Instant, callbackUrl: String) object PulledItem { @@ -33,4 +32,3 @@ object PulledItem { } } -// $COVERAGE-ON$ diff --git a/app/uk/gov/hmrc/ups/scheduling/LockedScheduledJob.scala b/app/uk/gov/hmrc/ups/scheduling/LockedScheduledJob.scala index da9f8ac..0c62420 100644 --- a/app/uk/gov/hmrc/ups/scheduling/LockedScheduledJob.scala +++ b/app/uk/gov/hmrc/ups/scheduling/LockedScheduledJob.scala @@ -22,7 +22,6 @@ import uk.gov.hmrc.mongo.lock.{ LockRepository, LockService } import scala.concurrent.duration.Duration import scala.concurrent.{ ExecutionContext, Future, duration } -//$COVERAGE-OFF$ trait LockedScheduledJob extends ScheduledJob { private val logger: Logger = Logger(getClass) @@ -48,4 +47,3 @@ trait LockedScheduledJob extends ScheduledJob { } } -//$COVERAGE-ON$ diff --git a/app/uk/gov/hmrc/ups/scheduling/RunModeBridge.scala b/app/uk/gov/hmrc/ups/scheduling/RunModeBridge.scala index a98aeef..270ba4e 100644 --- a/app/uk/gov/hmrc/ups/scheduling/RunModeBridge.scala +++ b/app/uk/gov/hmrc/ups/scheduling/RunModeBridge.scala @@ -21,7 +21,6 @@ import play.api.Configuration import javax.inject.{ Inject, Singleton } import scala.concurrent.duration._ -// $COVERAGE-OFF$ @Singleton class RunModeBridge @Inject() (configuration: Configuration) { @@ -49,4 +48,3 @@ class RunModeBridge @Inject() (configuration: Configuration) { .toMillis } -// $COVERAGE-ON$ diff --git a/app/uk/gov/hmrc/ups/scheduling/SchedulingConfig.scala b/app/uk/gov/hmrc/ups/scheduling/SchedulingConfig.scala index fe92702..0c9742b 100644 --- a/app/uk/gov/hmrc/ups/scheduling/SchedulingConfig.scala +++ b/app/uk/gov/hmrc/ups/scheduling/SchedulingConfig.scala @@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit import scala.concurrent.duration._ import scala.language.implicitConversions -//$COVERAGE-OFF$ trait SchedulingConfig { def runModeBridge: RunModeBridge @@ -57,4 +56,3 @@ trait SchedulingConfig { override def toString = s"'$name' initialDelay: ${initialDelay.toHM} interval: ${interval.toHM}" } -//$COVERAGE-ON$ diff --git a/build.sbt b/build.sbt index 93a9fbf..5b9ca88 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,6 @@ import play.sbt.routes.RoutesKeys import uk.gov.hmrc.DefaultBuildSettings._ +import scoverage.ScoverageKeys val appName = "updated-print-suppressions" @@ -29,7 +30,7 @@ lazy val microservice = Project(appName, file(".")) ) ) .settings(RoutesKeys.routesImport ++= Seq("uk.gov.hmrc.ups.model._")) - .settings(ScoverageSettings()) + .settings(ScoverageSettings().settings) lazy val it = project .enablePlugins(PlayScala, ScalafmtPlugin) @@ -43,11 +44,5 @@ lazy val it = project ) Test / test := (Test / test) - .dependsOn(scalafmtCheckAll) - .value - -// NOTE: the jenkins build does not currently execute the integration tests - -it / test := (it / Test / test) - .dependsOn(scalafmtCheckAll, it/scalafmtCheckAll) + .dependsOn(scalafmtCheckAll, it / Test / test) .value diff --git a/project/ScoverageSettings.scala b/project/ScoverageSettings.scala index 1470fb8..3082f54 100644 --- a/project/ScoverageSettings.scala +++ b/project/ScoverageSettings.scala @@ -19,12 +19,21 @@ import scoverage.ScoverageKeys import sbt._ object ScoverageSettings { + + val excludedPackages: Seq[String] = Seq( + "", + ".*Reverse.*", + ".*Routes.*", + ".*BuildInfo.*", + "testOnlyDoNotUseInAppConf.*", + ".*\\$anon.*" + ) + def apply(): Seq[Def.Setting[_ >: String with Double with Boolean]] = Seq( // Semicolon-separated list of regexes matching classes to exclude - ScoverageKeys.coverageExcludedPackages := ";.*Reverse.*;.*testonly.*;.*(BuildInfo|Routes).*;.*\\$anon.*", - ScoverageKeys.coverageMinimumStmtTotal := 40.90, + ScoverageKeys.coverageExcludedPackages := excludedPackages.mkString(","), + ScoverageKeys.coverageMinimumStmtTotal := 70.00, ScoverageKeys.coverageFailOnMinimum := true, - ScoverageKeys.coverageHighlighting := true, - ConfigKey.configurationToKey(Test) / parallelExecution := false + ScoverageKeys.coverageHighlighting := true ) } diff --git a/test/uk/gov/hmrc/ups/model/EntitySpec.scala b/test/uk/gov/hmrc/ups/model/EntitySpec.scala new file mode 100644 index 0000000..e822602 --- /dev/null +++ b/test/uk/gov/hmrc/ups/model/EntitySpec.scala @@ -0,0 +1,71 @@ +/* + * Copyright 2025 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.ups.model + +import org.scalatest.funsuite.AnyFunSuiteLike +import org.scalatestplus.play.PlaySpec +import play.api.libs.json.Json +import uk.gov.hmrc.domain.SaUtr +import uk.gov.hmrc.domain.TaxIds.TaxIdWithName + +import java.util.UUID + +class EntitySpec extends PlaySpec { + + "Entity" should { + "create an instance correctly" in { + val taxId: TaxIdWithName = SaUtr("1234567890") + taxId.name mustBe "sautr" + taxId.value mustBe "1234567890" + + } + } + + "toStrings" should { + "convert tax identifiers to strings correctly" in { + val taxId1: TaxIdWithName = SaUtr("1234567890") + val taxId2: TaxIdWithName = SaUtr("0987654321") + val taxIds: Set[TaxIdWithName] = Set(taxId1, taxId2) + + val result: Set[String] = Entity.toStrings(taxIds) + + result must contain("sautr: 1234567890") + result must contain("sautr: 0987654321") + } + } + + "reads" should { + "deserialize JSON to Entity correctly" in { + val entityId = UUID.randomUUID().toString + val jsonString = + s""" + |{ + | "_id": "$entityId", + | "sautr": "1234567890" + |} + |""".stripMargin + + val json = Json.parse(jsonString) + val entity = json.as[Entity] + + entity.id.value mustBe entityId + entity.taxIdentifiers.head.name mustBe "sautr" + entity.taxIdentifiers.head.value mustBe "1234567890" + } + } + +} diff --git a/test/uk/gov/hmrc/ups/model/FiltersSpec.scala b/test/uk/gov/hmrc/ups/model/FiltersSpec.scala new file mode 100644 index 0000000..ec02ca4 --- /dev/null +++ b/test/uk/gov/hmrc/ups/model/FiltersSpec.scala @@ -0,0 +1,46 @@ +/* + * Copyright 2025 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.ups.model + +import org.scalatest.funsuite.AnyFunSuiteLike +import org.scalatestplus.play.PlaySpec + +class FiltersSpec extends PlaySpec { + + "Filters" should { + "create an instance correctly" in { + val filters = Filters( + failedBefore = java.time.Instant.parse("2024-01-01T00:00:00Z"), + availableBefore = java.time.Instant.parse("2024-01-02T00:00:00Z") + ) + + filters.failedBefore mustBe java.time.Instant.parse("2024-01-01T00:00:00Z") + filters.availableBefore mustBe java.time.Instant.parse("2024-01-02T00:00:00Z") + } + + "format" in { + val filters = Filters( + failedBefore = java.time.Instant.parse("2024-01-01T00:00:00Z"), + availableBefore = java.time.Instant.parse("2024-01-02T00:00:00Z") + ) + + filters.failedBefore.toString mustBe "2024-01-01T00:00:00Z" + filters.availableBefore.toString mustBe "2024-01-02T00:00:00Z" + } + } + +} diff --git a/test/uk/gov/hmrc/ups/model/PulledItemSpec.scala b/test/uk/gov/hmrc/ups/model/PulledItemSpec.scala new file mode 100644 index 0000000..90f8e30 --- /dev/null +++ b/test/uk/gov/hmrc/ups/model/PulledItemSpec.scala @@ -0,0 +1,40 @@ +/* + * Copyright 2025 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.ups.model + +import org.scalatest.funsuite.AnyFunSuiteLike +import org.scalatestplus.play.PlaySpec +import play.api.libs.json.Json +import uk.gov.hmrc.ups.utils.DateFormats.instantFormats +import java.util.UUID + +class PulledItemSpec extends PlaySpec { + "PulledItem" should { + "serialize and deserialize" in { + implicit val pulledItemFormat = PulledItem.formats + val originalPulledItem = PulledItem( + entityId = EntityId("some-id"), + paperless = true, + updatedAt = instantFormats.reads(Json.parse("\"2024-06-10T12:34:56Z\"")).get, + callbackUrl = s"https://callback.url/${UUID.randomUUID()}" + ) + val json = Json.toJson(originalPulledItem) + val deserializedPulledItem = json.as[PulledItem] + deserializedPulledItem mustEqual originalPulledItem + } + } +} diff --git a/test/uk/gov/hmrc/ups/model/UpdatedPrintPreferencesSpec.scala b/test/uk/gov/hmrc/ups/model/UpdatedPrintPreferencesSpec.scala new file mode 100644 index 0000000..5e337b9 --- /dev/null +++ b/test/uk/gov/hmrc/ups/model/UpdatedPrintPreferencesSpec.scala @@ -0,0 +1,42 @@ +/* + * Copyright 2025 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.ups.model + +import org.scalatest.funsuite.AnyFunSuiteLike +import org.scalatestplus.play.PlaySpec +import play.api.libs.json.{ Json, OFormat } + +class UpdatedPrintPreferencesSpec extends PlaySpec { + + "UpdatedPrintPreferences" should { + + "serialize and deserialize correctly" in { + implicit val uppFormat: OFormat[UpdatedPrintPreferences] = UpdatedPrintPreferences.formats + val originalUpp = UpdatedPrintPreferences( + pages = 2, + next = Some("next-page-token"), + updates = List( + PrintPreference("some-id", "sautr", List("some-form")) + ) + ) + val json = Json.toJson(originalUpp) + val deserializedUpp = json.as[UpdatedPrintPreferences] + deserializedUpp mustEqual originalUpp + } + } + +} diff --git a/test/uk/gov/hmrc/ups/repository/CounterSpec.scala b/test/uk/gov/hmrc/ups/repository/CounterSpec.scala new file mode 100644 index 0000000..16ceddb --- /dev/null +++ b/test/uk/gov/hmrc/ups/repository/CounterSpec.scala @@ -0,0 +1,41 @@ +/* + * Copyright 2025 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.ups.repository + +import org.scalatest.funsuite.AnyFunSuiteLike +import org.scalatestplus.play.PlaySpec +import org.mongodb.scala.bson.ObjectId +import play.api.libs.json.Json +import uk.gov.hmrc.mongo.play.json.formats.MongoFormats + +class CounterSpec extends PlaySpec { + + "Counter" should { + "serialize and deserialize correctly" in { + + implicit val objectIdFormat = MongoFormats.objectIdFormat + implicit val counterFormat = Counter.formats + + val originalCounter = Counter(new ObjectId(), "test-counter", 42) + val json = Json.toJson(originalCounter) + val deserializedCounter = json.as[Counter] + + deserializedCounter mustEqual originalCounter + } + } + +} diff --git a/test/uk/gov/hmrc/ups/scheduling/SchedulingConfigSpec.scala b/test/uk/gov/hmrc/ups/scheduling/SchedulingConfigSpec.scala new file mode 100644 index 0000000..44d4828 --- /dev/null +++ b/test/uk/gov/hmrc/ups/scheduling/SchedulingConfigSpec.scala @@ -0,0 +1,85 @@ +/* + * Copyright 2025 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.ups.scheduling + +import org.mockito.Mockito._ +import org.scalatestplus.mockito.MockitoSugar +import org.scalatestplus.play.PlaySpec +import scala.concurrent.duration._ + +class SchedulingConfigSpec extends PlaySpec with MockitoSugar { + + "SchedulingConfig" should { + "load initialDelay from configuration" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getMillisForScheduling("some-job", "initialDelay")) + .thenReturn(500.milliseconds) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.initialDelay mustBe 500.milliseconds + } + + "load interval from configuration" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getMillisForScheduling("some-job", "interval")) + .thenReturn(1000.milliseconds) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.interval mustBe 1000.milliseconds + } + + "load optional lockDuration from configuration" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getOptionalMillisForScheduling("some-job", "lockDuration")) + .thenReturn(Some(2.hours)) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.lockDuration mustBe Some(2.hours) + } + + "return None for lockDuration when not configured" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getOptionalMillisForScheduling("some-job", "lockDuration")) + .thenReturn(None) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.lockDuration mustBe None + } + + "load taskEnabled flag from configuration" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getEnabledFlag("some-job", "taskEnabled")).thenReturn(true) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.taskEnabled mustBe true + } + + "load batchSize from configuration" in { + val mockRunModeBridge = mock[RunModeBridge] + when(mockRunModeBridge.getBatchSize("some-job", "batchSize")).thenReturn(100) + + val config = new TestSchedulingConfig(mockRunModeBridge) + config.batchSize mustBe 100 + } + + } + + private class TestSchedulingConfig(val runModeBridge: RunModeBridge) extends SchedulingConfig { + val name: String = "some-job" + } + +} diff --git a/test/uk/gov/hmrc/ups/utils/DateConverterSpec.scala b/test/uk/gov/hmrc/ups/utils/DateConverterSpec.scala new file mode 100644 index 0000000..d7d378b --- /dev/null +++ b/test/uk/gov/hmrc/ups/utils/DateConverterSpec.scala @@ -0,0 +1,58 @@ +/* + * 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.ups.utils + +import org.scalatest.concurrent.ScalaFutures +import org.scalatest.wordspec.AnyWordSpec +import org.scalatest.matchers.must.Matchers.* + +import java.time.format.DateTimeParseException +import java.time.{ Instant, LocalDate, ZoneId } + +class DateConverterSpec extends AnyWordSpec with ScalaFutures { + + "parseToLocalDate" should { + "parse a valid date string" in { + val date = "2026-11-01" + val result = DateConverter.parseToLocalDate(date) + result mustBe LocalDate.of(2026, 11, 1) + } + + "throw DateTimeParseException for invalid format" in { + intercept[DateTimeParseException] { + DateConverter.parseToLocalDate("15/11/2026") + } + } + + } + + "formatToString from LocalDate" should { + "format a LocalDate to ISO date string" in { + val date = LocalDate.of(2025, 11, 1) + val result = DateConverter.formatToString(date) + result mustBe "2025-11-01" + } + } + + "dateFormatter" should { + "be ISO_DATE format (yyyy-MM-dd)" in { + val date = LocalDate.of(2025, 11, 1) + val formatted = DateConverter.formatToString(date) + formatted mustBe "2025-11-01" + } + } +} diff --git a/test/uk/gov/hmrc/ups/utils/GenerateSpec.scala b/test/uk/gov/hmrc/ups/utils/GenerateSpec.scala new file mode 100644 index 0000000..0dada37 --- /dev/null +++ b/test/uk/gov/hmrc/ups/utils/GenerateSpec.scala @@ -0,0 +1,46 @@ +/* + * Copyright 2025 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.ups.utils + +import org.scalatestplus.play.PlaySpec +import uk.gov.hmrc.domain.{ Nino, SaUtr } +import uk.gov.hmrc.ups.model.EntityId + +class GenerateSpec extends PlaySpec { + + "Generate" should { + "nino" in { + val nino = Generate.nino + nino mustBe a[Nino] + + nino.value.nonEmpty mustBe true + + nino.value.matches("""^[A-Z]{2}[0-9]{6}[A-Z]""") mustBe true + + } + "utr" in { + val utr = Generate.utr + utr mustBe a[SaUtr] + } + + "entityId" in { + val entityId = Generate.entityId + entityId mustBe a[EntityId] + } + } + +}