Skip to content

Commit

Permalink
[Tech] re-add validation on reportings and vigilance areas
Browse files Browse the repository at this point in the history
  • Loading branch information
claire2212 authored and maximeperraultdev committed Feb 17, 2025
1 parent b7fd8c6 commit 5f85b85
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package fr.gouv.cacem.monitorenv.domain.use_cases.reportings

// import fr.gouv.cacem.monitorenv.domain.validators.reporting.ReportingValidator
import fr.gouv.cacem.monitorenv.config.UseCase
import fr.gouv.cacem.monitorenv.domain.entities.reporting.ReportingEntity
import fr.gouv.cacem.monitorenv.domain.exceptions.ReportingAlreadyAttachedException
import fr.gouv.cacem.monitorenv.domain.repositories.*
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.dtos.ReportingDetailsDTO
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.events.UpdateReportingEvent
import fr.gouv.cacem.monitorenv.domain.validators.UseCaseValidation
import fr.gouv.cacem.monitorenv.domain.validators.reporting.ReportingValidator
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationEventPublisher
Expand All @@ -22,7 +23,7 @@ class CreateOrUpdateReporting(

@Throws(IllegalArgumentException::class)
fun execute(
// @UseCaseValidation<ReportingEntity>(validator = ReportingValidator::class)
@UseCaseValidation<ReportingEntity>(validator = ReportingValidator::class)
reporting: ReportingEntity,
): ReportingDetailsDTO {
logger.info("Attempt to CREATE or UPDATE reporting ${reporting.id}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.repositories.IFacadeAreasRepository
import fr.gouv.cacem.monitorenv.domain.repositories.IVigilanceAreaRepository
import fr.gouv.cacem.monitorenv.domain.use_cases.dashboard.SaveDashboard
// import fr.gouv.cacem.monitorenv.domain.validators.vigilance_area.VigilanceAreaValidator
import fr.gouv.cacem.monitorenv.domain.validators.UseCaseValidation
import fr.gouv.cacem.monitorenv.domain.validators.vigilance_area.VigilanceAreaValidator
import org.slf4j.LoggerFactory

@UseCase
Expand All @@ -18,7 +19,7 @@ class CreateOrUpdateVigilanceArea(
private val logger = LoggerFactory.getLogger(SaveDashboard::class.java)

fun execute(
// @UseCaseValidation<VigilanceAreaEntity>(validator = VigilanceAreaValidator::class)
@UseCaseValidation<VigilanceAreaEntity>(validator = VigilanceAreaValidator::class)
vigilanceArea: VigilanceAreaEntity,
): VigilanceAreaEntity {
logger.info("Attempt to CREATE or UPDATE vigilance area ${vigilanceArea.id}")
Expand All @@ -28,13 +29,17 @@ class CreateOrUpdateVigilanceArea(
facadeAreasRepository.findFacadeFromGeometry(nonNullGeom)
}

val savedVigilanceArea = vigilanceAreaRepository.save(vigilanceArea.copy(seaFront = seaFront))
val savedVigilanceArea =
vigilanceAreaRepository.save(vigilanceArea.copy(seaFront = seaFront))
logger.info("Vigilance area ${savedVigilanceArea.id} created or updated")
return savedVigilanceArea
} catch (e: Exception) {
val errorMessage = "vigilance area ${vigilanceArea.id} couldn't be saved"
logger.error(errorMessage, e)
throw BackendUsageException(BackendUsageErrorCode.ENTITY_NOT_SAVED, message = errorMessage)
throw BackendUsageException(
BackendUsageErrorCode.ENTITY_NOT_SAVED,
message = errorMessage,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,70 +1,119 @@
package fr.gouv.cacem.monitorenv.domain.validators.reporting

import fr.gouv.cacem.monitorenv.domain.entities.reporting.TargetTypeEnum
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.fixtures.ReportingFixture.Companion.aReporting
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.fixtures.ReportingFixture.Companion.aReportingSourceControlUnit
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.fixtures.ReportingFixture.Companion.aReportingSourceOther
import fr.gouv.cacem.monitorenv.domain.use_cases.reportings.fixtures.ReportingFixture.Companion.aReportingSourceSemaphore
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource

class ReportingValidatorUTest {
private val reportingValidator = ReportingValidator()

/* @ParameterizedTest
@ParameterizedTest
@ValueSource(strings = ["A", "AA", "AAAA"])
fun `validate should throw an exception if there is a control with openBy is not a trigram`(openBy: String) {
val reporting = aReporting(openBy = openBy)

val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
assertThat(assertThrows.message).isEqualTo("Le trigramme \"ouvert par\" doit avoir 3 lettres")
val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message)
.isEqualTo("Le trigramme \"ouvert par\" doit avoir 3 lettres")
}

@Test
fun `validate should throw an exception if reportingSource is empty`() {
val reporting = aReporting(reportingSources = listOf())

val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("Une source du signalement est obligatoire")
}

@Test
fun `validate should throw an exception if reportingSource from control unit is invalid`() {
val reporting = aReporting(reportingSources = listOf(aReportingSourceControlUnit().copy(semaphoreId = 1)))
val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val reporting =
aReporting(
reportingSources =
listOf(aReportingSourceControlUnit().copy(semaphoreId = 1)),
)

val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("La source du signalement est invalide")
}

@Test
fun `validate should throw an exception if reportingSource from semaphore is invalid`() {
val reporting = aReporting(reportingSources = listOf(aReportingSourceSemaphore().copy(sourceName = "test")))
val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val reporting =
aReporting(
reportingSources =
listOf(aReportingSourceSemaphore().copy(sourceName = "test")),
)

val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("La source du signalement est invalide")
}

@Test
fun `validate should throw an exception if reportingSource from other is invalid`() {
val reporting = aReporting(reportingSources = listOf(aReportingSourceOther().copy(controlUnitId = 1)))
val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val reporting =
aReporting(
reportingSources = listOf(aReportingSourceOther().copy(controlUnitId = 1)),
)

val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("La source du signalement est invalide")
}

@Test
fun `validate should throw an exception if validityTime is less than 1`() {
val reporting = aReporting(validityTime = 0)

val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
assertThat(assertThrows.message).isEqualTo("La validité du signalement doit être supérieur à 0")
val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message)
.isEqualTo("La validité du signalement doit être supérieur à 0")
}

@Test
fun `validate should throw an exception if subthemeIds is empty`() {
val reporting = aReporting(subThemeIds = listOf())

val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("Un sous-thème est obligatoire")
}

@Test
fun `validate should throw an exception if targetType is OTHER without description`() {
val reporting = aReporting(targetType = TargetTypeEnum.OTHER, description = null)

val assertThrows = assertThrows(BackendUsageException::class.java) { reportingValidator.validate(reporting) }
val assertThrows =
assertThrows(BackendUsageException::class.java) {
reportingValidator.validate(reporting)
}
assertThat(assertThrows.message).isEqualTo("La description de la cible est obligatoire")
}

Expand All @@ -73,5 +122,5 @@ class ReportingValidatorUTest {
val reporting = aReporting()

reportingValidator.validate(reporting)
} */
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package fr.gouv.cacem.monitorenv.domain.validators.vigilance_area

import fr.gouv.cacem.monitorenv.domain.entities.vigilanceArea.EndingConditionEnum
import fr.gouv.cacem.monitorenv.domain.exceptions.BackendUsageException
import fr.gouv.cacem.monitorenv.domain.use_cases.vigilanceArea.fixtures.VigilanceAreaFixture.Companion.aVigilanceAreaEntity
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.NullSource
import org.junit.jupiter.params.provider.ValueSource

class VigilanceAreaValidatorUTest {
private val vigilanceAreaValidator = VigilanceAreaValidator()

/* @ParameterizedTest
@ParameterizedTest
@ValueSource(strings = ["A", "AA", "AAAA"])
fun `validate should throw an exception if createdBy is not a trigram when it is published`(createdBy: String) {
val vigilanceArea = aVigilanceAreaEntity(createdBy = createdBy, isDraft = false)
Expand Down Expand Up @@ -144,5 +154,5 @@ class VigilanceAreaValidatorUTest {
val vigilanceArea = aVigilanceAreaEntity()

vigilanceAreaValidator.validate(vigilanceArea)
} */
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ import * as Yup from 'yup'

import { ClosedControlPlansSchema, NewControlPlansSchema } from './ControlPlans'
import { type Awareness, type EnvActionSurveillance } from '../../../../../domain/entities/missions'
import { isCypress } from '../../../../../utils/isCypress'
import { HIDDEN_ERROR } from '../constants'
import { actionEndDateValidation, actionStartDateValidation } from './ActionDates'

import type { ControlPlansData } from 'domain/entities/controlPlan'
import type { GeoJSON } from 'domain/types/GeoJSON'

const shouldUseAlternateValidationInTestEnvironment = !import.meta.env.PROD || isCypress()

export const getNewEnvActionSurveillanceSchema = (
ctx: any
): Yup.Schema<Omit<EnvActionSurveillance, 'actionType' | 'completion' | 'reportingIds'>> =>
Expand All @@ -29,9 +26,7 @@ export const getNewEnvActionSurveillanceSchema = (
.optional(),
controlPlans: Yup.array<ControlPlansData>().of(NewControlPlansSchema).optional(),
durationMatchesMission: Yup.boolean().optional(),
geom: shouldUseAlternateValidationInTestEnvironment
? Yup.mixed<GeoJSON.MultiPolygon>().optional()
: Yup.mixed<GeoJSON.MultiPolygon>().required('Veuillez définir une zone de surveillance'),
geom: Yup.mixed<GeoJSON.MultiPolygon>().required('Veuillez définir une zone de surveillance'),
id: Yup.string().required(),
observations: Yup.string().optional(),
openBy: Yup.string()
Expand Down Expand Up @@ -59,9 +54,7 @@ export const getCompletionEnvActionSurveillanceSchema = (
.optional(),
controlPlans: Yup.array().ensure().of(ClosedControlPlansSchema).ensure().required().min(1),
durationMatchesMission: Yup.boolean().optional(),
geom: shouldUseAlternateValidationInTestEnvironment
? Yup.mixed<GeoJSON.MultiPolygon>().optional()
: Yup.mixed<GeoJSON.MultiPolygon>().required('Veuillez définir une zone de surveillance'),
geom: Yup.mixed<GeoJSON.MultiPolygon>().required('Veuillez définir une zone de surveillance'),
id: Yup.string().required(),
observations: Yup.string().optional(),
openBy: Yup.string()
Expand Down
17 changes: 10 additions & 7 deletions frontend/src/features/Mission/useCases/saveMission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,18 @@ export const saveMission =
missionUpdated,
reportings
})
} else if ('data' in response.error) {
if (response.error.data?.type === ApiErrorCode.CHILD_ALREADY_ATTACHED) {
throw Error('Le signalement est déjà rattaché à une mission')
}
if (response.error.data?.code === ApiErrorCode.UNVALID_PROPERTY) {
throw Error('Une propriété est invalide')
} else {
if ('data' in response.error) {
if (response.error.data?.type === ApiErrorCode.CHILD_ALREADY_ATTACHED) {
throw Error('Le signalement est déjà rattaché à une mission')
}
if (response.error.data?.code === ApiErrorCode.UNVALID_PROPERTY) {
throw Error('Une propriété est invalide')
}
}

throw Error('Erreur à la création ou à la modification de la mission')
}
throw Error('Erreur à la création ou à la modification de la mission')
} catch (error) {
dispatch(setToast({ containerId: 'sideWindow', message: error }))
}
Expand Down

0 comments on commit 5f85b85

Please sign in to comment.