Merge branch 'features-dev' into 'features'
Ajout de la vérification des étapes des recettes et des ingrédients des mélanges See merge request color-recipes-explorer/backend!24
This commit is contained in:
commit
a227ce21a1
|
@ -11,5 +11,6 @@ logs/
|
|||
data/
|
||||
dokka/
|
||||
dist/
|
||||
out/
|
||||
|
||||
/src/main/resources/angular/static/*
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package dev.fyloz.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.RestException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.MixMaterialRepository
|
||||
import dev.fyloz.colorrecipesexplorer.service.utils.findDuplicated
|
||||
import dev.fyloz.colorrecipesexplorer.service.utils.hasGaps
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface MixMaterialService : ModelService<MixMaterial, MixMaterialRepository> {
|
||||
|
@ -17,6 +21,13 @@ interface MixMaterialService : ModelService<MixMaterial, MixMaterialRepository>
|
|||
|
||||
/** Updates the [quantity] of the given [mixMaterial]. */
|
||||
fun updateQuantity(mixMaterial: MixMaterial, quantity: Float): MixMaterial
|
||||
|
||||
/**
|
||||
* Validates if the given [mixMaterials]. To be valid, the position of each mix material must be greater or equals to 1 and unique in the set.
|
||||
* There must also be no gap between the positions. Also, the quantity of the first mix material in the set must not be expressed in percentages.
|
||||
* If any of those criteria are not met, an [InvalidGroupStepsPositionsException] will be thrown.
|
||||
*/
|
||||
fun validateMixMaterials(mixMaterials: Set<MixMaterial>)
|
||||
}
|
||||
|
||||
@Service
|
||||
|
@ -42,4 +53,90 @@ class MixMaterialServiceImpl(
|
|||
update(mixMaterial.apply {
|
||||
this.quantity = quantity
|
||||
})
|
||||
|
||||
override fun validateMixMaterials(mixMaterials: Set<MixMaterial>) {
|
||||
if (mixMaterials.isEmpty()) return
|
||||
|
||||
val sortedMixMaterials = mixMaterials.sortedBy { it.position }
|
||||
val firstMixMaterial = sortedMixMaterials[0]
|
||||
val errors = mutableSetOf<InvalidMixMaterialsPositionsError>()
|
||||
|
||||
// Check if the first mix material position is 1
|
||||
fun isFirstMixMaterialPositionInvalid() =
|
||||
sortedMixMaterials[0].position != 1
|
||||
|
||||
// Check if the first mix material is expressed in percents
|
||||
fun isFirstMixMaterialPercentages() =
|
||||
sortedMixMaterials[0].material.materialType!!.usePercentages
|
||||
|
||||
// Check if any positions is duplicated
|
||||
fun getDuplicatedPositionsErrors() =
|
||||
sortedMixMaterials
|
||||
.findDuplicated { it.position }
|
||||
.map { duplicatedMixMaterialsPositions(it) }
|
||||
|
||||
// Find all errors and throw if there is any
|
||||
if (isFirstMixMaterialPositionInvalid()) errors += invalidFirstMixMaterialPosition(sortedMixMaterials[0])
|
||||
errors += getDuplicatedPositionsErrors()
|
||||
if (errors.isEmpty() && mixMaterials.hasGaps { it.position }) errors += gapBetweenStepsPositions()
|
||||
if (errors.isNotEmpty()) {
|
||||
throw InvalidMixMaterialsPositionsException(errors)
|
||||
}
|
||||
|
||||
if (isFirstMixMaterialPercentages()) {
|
||||
throw InvalidFirstMixMaterial(firstMixMaterial)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidMixMaterialsPositionsError(
|
||||
val type: String,
|
||||
val details: String
|
||||
)
|
||||
|
||||
class InvalidMixMaterialsPositionsException(
|
||||
val errors: Set<InvalidMixMaterialsPositionsError>
|
||||
) : RestException(
|
||||
"invalid-mixmaterial-position",
|
||||
"Invalid mix materials positions",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"The position of mix materials are invalid",
|
||||
mapOf(
|
||||
"invalidMixMaterials" to errors
|
||||
)
|
||||
)
|
||||
|
||||
class InvalidFirstMixMaterial(
|
||||
val mixMaterial: MixMaterial
|
||||
) : RestException(
|
||||
"invalid-mixmaterial-first",
|
||||
"Invalid first mix material",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"The first mix material is invalid because its material must not be expressed in percents",
|
||||
mapOf(
|
||||
"mixMaterial" to mixMaterial
|
||||
)
|
||||
)
|
||||
|
||||
const val INVALID_FIRST_MIX_MATERIAL_POSITION_ERROR_CODE = "first"
|
||||
const val DUPLICATED_MIX_MATERIALS_POSITIONS_ERROR_CODE = "duplicated"
|
||||
const val GAP_BETWEEN_MIX_MATERIALS_POSITIONS_ERROR_CODE = "gap"
|
||||
|
||||
private fun invalidFirstMixMaterialPosition(mixMaterial: MixMaterial) =
|
||||
InvalidMixMaterialsPositionsError(
|
||||
INVALID_FIRST_MIX_MATERIAL_POSITION_ERROR_CODE,
|
||||
"The position ${mixMaterial.position} is under the minimum of 1"
|
||||
)
|
||||
|
||||
private fun duplicatedMixMaterialsPositions(position: Int) =
|
||||
InvalidMixMaterialsPositionsError(
|
||||
DUPLICATED_MIX_MATERIALS_POSITIONS_ERROR_CODE,
|
||||
"The position $position is duplicated"
|
||||
)
|
||||
|
||||
private fun gapBetweenStepsPositions() =
|
||||
InvalidMixMaterialsPositionsError(
|
||||
GAP_BETWEEN_MIX_MATERIALS_POSITIONS_ERROR_CODE,
|
||||
"There is a gap between mix materials positions"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package dev.fyloz.colorrecipesexplorer.service
|
||||
|
||||
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.MixRepository
|
||||
import dev.fyloz.colorrecipesexplorer.service.utils.setAll
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.stereotype.Service
|
||||
import javax.transaction.Transactional
|
||||
|
@ -43,6 +43,8 @@ class MixServiceImpl(
|
|||
val mixType = mixTypeService.getOrCreateForNameAndMaterialType(entity.name, materialType)
|
||||
|
||||
val mixMaterials = if (entity.mixMaterials != null) mixMaterialService.create(entity.mixMaterials) else setOf()
|
||||
mixMaterialService.validateMixMaterials(mixMaterials)
|
||||
|
||||
var mix = mix(recipe = recipe, mixType = mixType, mixMaterials = mixMaterials.toMutableSet())
|
||||
mix = save(mix)
|
||||
|
||||
|
@ -68,8 +70,7 @@ class MixServiceImpl(
|
|||
}
|
||||
}
|
||||
if (entity.mixMaterials != null) {
|
||||
mix.mixMaterials.clear()
|
||||
mix.mixMaterials.addAll(mixMaterialService.create(entity.mixMaterials!!).toMutableSet())
|
||||
mix.mixMaterials.setAll(mixMaterialService.create(entity.mixMaterials!!).toMutableSet())
|
||||
}
|
||||
return update(mix)
|
||||
}
|
||||
|
|
|
@ -3,20 +3,21 @@ package dev.fyloz.colorrecipesexplorer.service
|
|||
import dev.fyloz.colorrecipesexplorer.exception.RestException
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
|
||||
import dev.fyloz.colorrecipesexplorer.service.utils.findDuplicated
|
||||
import dev.fyloz.colorrecipesexplorer.service.utils.hasGaps
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
interface RecipeStepService : ModelService<RecipeStep, RecipeStepRepository> {
|
||||
/**
|
||||
* Validates if the steps of the given [groupInformation] obey the following criteria:
|
||||
*
|
||||
* * The position of the steps is greater or equals to 1
|
||||
* * Each position is unique in the collection
|
||||
* * There is no gap between positions
|
||||
*
|
||||
* If any of those criteria are not met, an [InvalidStepsPositionsException] will be thrown.
|
||||
*/
|
||||
/** Validates the steps of the given [groupInformation], according to the criteria of [validateSteps]. */
|
||||
fun validateGroupInformationSteps(groupInformation: RecipeGroupInformation)
|
||||
|
||||
/**
|
||||
* Validates if the given [steps]. To be valid, the position of each step must be greater or equals to 1 and unique in the set.
|
||||
* There must also be no gap between the positions.
|
||||
* If any of those criteria are not met, an [InvalidGroupStepsPositionsException] will be thrown.
|
||||
*/
|
||||
fun validateSteps(steps: Set<RecipeStep>)
|
||||
}
|
||||
|
||||
@Service
|
||||
|
@ -27,10 +28,17 @@ class RecipeStepServiceImpl(recipeStepRepository: RecipeStepRepository) :
|
|||
override fun idAlreadyExistsException(id: Long) = recipeStepIdAlreadyExistsException(id)
|
||||
|
||||
override fun validateGroupInformationSteps(groupInformation: RecipeGroupInformation) {
|
||||
val steps = groupInformation.steps
|
||||
val group = groupInformation.group
|
||||
if (groupInformation.steps == null) return
|
||||
|
||||
if (steps == null) return
|
||||
try {
|
||||
validateSteps(groupInformation.steps!!)
|
||||
} catch (validationException: InvalidStepsPositionsException) {
|
||||
throw InvalidGroupStepsPositionsException(groupInformation.group, validationException)
|
||||
}
|
||||
}
|
||||
|
||||
override fun validateSteps(steps: Set<RecipeStep>) {
|
||||
if (steps.isEmpty()) return
|
||||
|
||||
val sortedSteps = steps.sortedBy { it.position }
|
||||
val errors = mutableSetOf<InvalidStepsPositionsError>()
|
||||
|
@ -42,23 +50,15 @@ class RecipeStepServiceImpl(recipeStepRepository: RecipeStepRepository) :
|
|||
// Check if any position is duplicated
|
||||
fun getDuplicatedPositionsErrors() =
|
||||
sortedSteps
|
||||
.groupBy { it.position }
|
||||
.filter { it.value.count() > 1 }
|
||||
.map { duplicatedStepsPositions(it.key, group) }
|
||||
|
||||
// Check if there is any gap between steps positions
|
||||
// Knowing that steps are sorted by position, if the position of the step is not index + 1, there is a gap between them
|
||||
fun hasGapBetweenPositions() =
|
||||
sortedSteps
|
||||
.filterIndexed { index, step -> step.position != index + 1 }
|
||||
.isNotEmpty()
|
||||
.findDuplicated { it.position }
|
||||
.map { duplicatedStepsPositions(it) }
|
||||
|
||||
// Find all errors and throw if there is any
|
||||
if (isFirstStepPositionInvalid()) errors += invalidFirstStepPosition(sortedSteps[0])
|
||||
errors += getDuplicatedPositionsErrors()
|
||||
if (errors.isEmpty() && hasGapBetweenPositions()) errors += gapBetweenStepsPositions(group)
|
||||
if (errors.isEmpty() && steps.hasGaps { it.position }) errors += gapBetweenStepsPositions()
|
||||
if (errors.isNotEmpty()) {
|
||||
throw InvalidStepsPositionsException(group, errors)
|
||||
throw InvalidStepsPositionsException(errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,43 +69,53 @@ data class InvalidStepsPositionsError(
|
|||
)
|
||||
|
||||
class InvalidStepsPositionsException(
|
||||
val group: EmployeeGroup,
|
||||
val errors: Set<InvalidStepsPositionsError>
|
||||
) :
|
||||
RestException(
|
||||
"invalid-recipestep-position",
|
||||
"Invalid steps position",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"The position of steps for the group ${group.name} are invalid",
|
||||
mapOf(
|
||||
"group" to group.name,
|
||||
"groupId" to group.id!!,
|
||||
"invalidSteps" to errors
|
||||
)
|
||||
) : RestException(
|
||||
"invalid-recipestep-position",
|
||||
"Invalid steps positions",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"The position of steps are invalid",
|
||||
mapOf(
|
||||
"invalidSteps" to errors
|
||||
)
|
||||
)
|
||||
|
||||
class InvalidGroupStepsPositionsException(
|
||||
val group: EmployeeGroup,
|
||||
val exception: InvalidStepsPositionsException
|
||||
) : RestException(
|
||||
"invalid-groupinformation-recipestep-position",
|
||||
"Invalid steps positions",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"The position of steps for the group ${group.name} are invalid",
|
||||
mapOf(
|
||||
"group" to group.name,
|
||||
"groupId" to group.id!!,
|
||||
"invalidSteps" to exception.errors
|
||||
)
|
||||
) {
|
||||
val errors: Set<InvalidStepsPositionsError>
|
||||
get() = exception.errors
|
||||
}
|
||||
|
||||
const val INVALID_FIRST_STEP_POSITION_ERROR_CODE = "first"
|
||||
const val DUPLICATED_STEPS_POSITIONS_ERROR_CODE = "duplicated"
|
||||
const val GAP_BETWEEN_STEPS_POSITIONS_ERROR_CODE = "gap"
|
||||
|
||||
private fun invalidFirstStepPosition(
|
||||
step: RecipeStep
|
||||
) = InvalidStepsPositionsError(
|
||||
INVALID_FIRST_STEP_POSITION_ERROR_CODE,
|
||||
"The position ${step.position} is under the minimum of 1"
|
||||
)
|
||||
private fun invalidFirstStepPosition(step: RecipeStep) =
|
||||
InvalidStepsPositionsError(
|
||||
INVALID_FIRST_STEP_POSITION_ERROR_CODE,
|
||||
"The position ${step.position} is under the minimum of 1"
|
||||
)
|
||||
|
||||
private fun duplicatedStepsPositions(
|
||||
position: Int,
|
||||
group: EmployeeGroup
|
||||
) = InvalidStepsPositionsError(
|
||||
DUPLICATED_STEPS_POSITIONS_ERROR_CODE,
|
||||
"The position $position is duplicated in the group ${group.name}"
|
||||
)
|
||||
private fun duplicatedStepsPositions(position: Int) =
|
||||
InvalidStepsPositionsError(
|
||||
DUPLICATED_STEPS_POSITIONS_ERROR_CODE,
|
||||
"The position $position is duplicated"
|
||||
)
|
||||
|
||||
private fun gapBetweenStepsPositions(
|
||||
group: EmployeeGroup
|
||||
) = InvalidStepsPositionsError(
|
||||
GAP_BETWEEN_STEPS_POSITIONS_ERROR_CODE,
|
||||
"The positions for the steps of the group ${group.name} have gaps between them"
|
||||
)
|
||||
private fun gapBetweenStepsPositions() =
|
||||
InvalidStepsPositionsError(
|
||||
GAP_BETWEEN_STEPS_POSITIONS_ERROR_CODE,
|
||||
"There is a gap between steps positions"
|
||||
)
|
||||
|
|
|
@ -17,6 +17,20 @@ inline fun <T, R, reified E : Throwable> Iterable<T>.mapMayThrow(
|
|||
}
|
||||
}
|
||||
|
||||
/** Find duplicated in the given [Iterable] from keys obtained from the given [keySelector]. */
|
||||
inline fun <T, K> Iterable<T>.findDuplicated(keySelector: (T) -> K) =
|
||||
this.groupBy(keySelector)
|
||||
.filter { it.value.count() > 1 }
|
||||
.map { it.key }
|
||||
|
||||
/** Check if the given [Iterable] has gaps between each items, using keys obtained from the given [keySelector]. */
|
||||
inline fun <T> Iterable<T>.hasGaps(keySelector: (T) -> Int) =
|
||||
this.map(keySelector)
|
||||
.toIntArray()
|
||||
.sorted()
|
||||
.filterIndexed { index, it -> it != index + 1 }
|
||||
.isNotEmpty()
|
||||
|
||||
/** Clears and fills the given [MutableCollection] with the given [elements]. */
|
||||
fun <T> MutableCollection<T>.setAll(elements: Collection<T>) {
|
||||
this.clear()
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.nhaarman.mockitokotlin2.*
|
|||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.MixMaterialRepository
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotEquals
|
||||
|
@ -99,4 +100,70 @@ class MixMaterialServiceTest : AbstractModelServiceTest<MixMaterial, MixMaterial
|
|||
|
||||
assertEquals(found.quantity, quantity)
|
||||
}
|
||||
|
||||
// validateMixMaterials()
|
||||
|
||||
@Test
|
||||
fun `validateMixMaterials() throws InvalidMixMaterialsPositionsException when the position of the first mix material is not 1`() {
|
||||
assertInvalidMixMaterialsPositionsException(
|
||||
setOf(
|
||||
mixMaterial(id = 0L, position = 0),
|
||||
mixMaterial(id = 1L, position = 1),
|
||||
mixMaterial(id = 2L, position = 2),
|
||||
mixMaterial(id = 3L, position = 3)
|
||||
),
|
||||
INVALID_FIRST_MIX_MATERIAL_POSITION_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateMixMaterials() throws InvalidMixMaterialsPositionsException when positions are duplicated`() {
|
||||
assertInvalidMixMaterialsPositionsException(
|
||||
setOf(
|
||||
mixMaterial(id = 0L, position = 1),
|
||||
mixMaterial(id = 1L, position = 2),
|
||||
mixMaterial(id = 2L, position = 2),
|
||||
mixMaterial(id = 3L, position = 3)
|
||||
),
|
||||
DUPLICATED_MIX_MATERIALS_POSITIONS_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateMixMaterials() throws InvalidMixMaterialsPositionsException when there is a gap between positions`() {
|
||||
assertInvalidMixMaterialsPositionsException(
|
||||
setOf(
|
||||
mixMaterial(id = 0L, position = 1),
|
||||
mixMaterial(id = 1L, position = 2),
|
||||
mixMaterial(id = 2L, position = 4),
|
||||
mixMaterial(id = 3L, position = 5)
|
||||
),
|
||||
GAP_BETWEEN_MIX_MATERIALS_POSITIONS_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateMixMaterials() throws InvalidFirstMixMaterial when the first mix material's quantity is expressed in percents`() {
|
||||
val normalMaterial = material(materialType = materialType(usePercentages = false))
|
||||
val percentsMaterial = material(materialType = materialType(usePercentages = true))
|
||||
val mixMaterials = setOf(
|
||||
mixMaterial(id = 0L, position = 1, material = percentsMaterial),
|
||||
mixMaterial(id = 1L, position = 2, material = normalMaterial),
|
||||
mixMaterial(id = 2L, position = 3, material = normalMaterial),
|
||||
mixMaterial(id = 3L, position = 4, material = normalMaterial)
|
||||
)
|
||||
|
||||
assertThrows<InvalidFirstMixMaterial> {
|
||||
service.validateMixMaterials(mixMaterials)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertInvalidMixMaterialsPositionsException(mixMaterials: Set<MixMaterial>, errorType: String) {
|
||||
val exception = assertThrows<InvalidMixMaterialsPositionsException> {
|
||||
service.validateMixMaterials(mixMaterials)
|
||||
}
|
||||
|
||||
assertTrue { exception.errors.size == 1 }
|
||||
assertTrue { exception.errors.first().type == errorType }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ class RecipeServiceTest :
|
|||
private val companyService: CompanyService = mock()
|
||||
private val mixService: MixService = mock()
|
||||
private val groupService: EmployeeGroupService = mock()
|
||||
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService, mixService, groupService))
|
||||
private val recipeStepService: RecipeStepService = mock()
|
||||
override val service: RecipeService = spy(RecipeServiceImpl(repository, companyService, mixService, recipeStepService, groupService))
|
||||
|
||||
private val company: Company = company(id = 0L)
|
||||
override val entity: Recipe = recipe(id = 0L, name = "recipe", company = company)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package dev.fyloz.colorrecipesexplorer.service
|
||||
|
||||
import com.nhaarman.mockitokotlin2.mock
|
||||
import com.nhaarman.mockitokotlin2.spy
|
||||
import com.nhaarman.mockitokotlin2.*
|
||||
import dev.fyloz.colorrecipesexplorer.model.*
|
||||
import dev.fyloz.colorrecipesexplorer.repository.RecipeStepRepository
|
||||
import org.junit.jupiter.api.Test
|
||||
|
@ -16,71 +15,89 @@ class RecipeStepServiceTest :
|
|||
override val entity: RecipeStep = recipeStep(id = 0L, message = "message")
|
||||
override val anotherEntity: RecipeStep = recipeStep(id = 1L, message = "another message")
|
||||
|
||||
// validateStepsCollection()
|
||||
// validateGroupInformationSteps()
|
||||
|
||||
@Test
|
||||
fun `validateStepsCollection() throws an InvalidStepsPositionsException when the position of the first step of the given groupInformation is not 1`() {
|
||||
withSteps(
|
||||
fun `validateGroupInformationSteps() calls validateSteps() with the given RecipeGroupInformation steps`() {
|
||||
withGroupInformation {
|
||||
service.validateGroupInformationSteps(this)
|
||||
|
||||
verify(service).validateSteps(this.steps!!)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateGroupInformationSteps() throws InvalidGroupStepsPositionsException when validateSteps() throws an InvalidStepsPositionsException`() {
|
||||
withGroupInformation {
|
||||
doAnswer { throw InvalidStepsPositionsException(setOf()) }.whenever(service).validateSteps(this.steps!!)
|
||||
|
||||
assertThrows<InvalidGroupStepsPositionsException> {
|
||||
service.validateGroupInformationSteps(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validateSteps()
|
||||
|
||||
@Test
|
||||
fun `validateSteps() throws an InvalidStepsPositionsException when the position of the first step of the given groupInformation is not 1`() {
|
||||
assertInvalidStepsPositionsException(
|
||||
mutableSetOf(
|
||||
recipeStep(id = 0L, position = 0),
|
||||
recipeStep(id = 1L, position = 1),
|
||||
recipeStep(id = 2L, position = 2),
|
||||
recipeStep(id = 3L, position = 3)
|
||||
)
|
||||
) {
|
||||
val exception = assertThrows<InvalidStepsPositionsException> {
|
||||
service.validateGroupInformationSteps(this)
|
||||
}
|
||||
|
||||
assertTrue { exception.errors.count() == 1 }
|
||||
assertTrue { exception.errors.first().type == INVALID_FIRST_STEP_POSITION_ERROR_CODE }
|
||||
}
|
||||
),
|
||||
INVALID_FIRST_STEP_POSITION_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateStepsCollection() throws an InvalidStepsPositionsException when steps positions are duplicated in the given groupInformation`() {
|
||||
withSteps(
|
||||
fun `validateSteps() throws an InvalidStepsPositionsException when steps positions are duplicated in the given groupInformation`() {
|
||||
assertInvalidStepsPositionsException(
|
||||
mutableSetOf(
|
||||
recipeStep(id = 0L, position = 1),
|
||||
recipeStep(id = 1L, position = 2),
|
||||
recipeStep(id = 2L, position = 2),
|
||||
recipeStep(id = 3L, position = 3)
|
||||
)
|
||||
) {
|
||||
val exception = assertThrows<InvalidStepsPositionsException> {
|
||||
service.validateGroupInformationSteps(this)
|
||||
}
|
||||
|
||||
assertTrue { exception.errors.count() == 1 }
|
||||
assertTrue { exception.errors.first().type == DUPLICATED_STEPS_POSITIONS_ERROR_CODE }
|
||||
}
|
||||
),
|
||||
DUPLICATED_STEPS_POSITIONS_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateStepsCollection() throws an InvalidStepsPositionsException when there is a gap between steps positions in the given groupInformation`() {
|
||||
withSteps(
|
||||
fun `validateSteps() throws an InvalidStepsPositionsException when there is a gap between steps positions in the given groupInformation`() {
|
||||
assertInvalidStepsPositionsException(
|
||||
mutableSetOf(
|
||||
recipeStep(id = 0L, position = 1),
|
||||
recipeStep(id = 1L, position = 2),
|
||||
recipeStep(id = 2L, position = 4),
|
||||
recipeStep(id = 3L, position = 5)
|
||||
)
|
||||
) {
|
||||
val exception = assertThrows<InvalidStepsPositionsException> {
|
||||
service.validateGroupInformationSteps(this)
|
||||
}
|
||||
|
||||
assertTrue { exception.errors.count() == 1 }
|
||||
assertTrue { exception.errors.first().type == GAP_BETWEEN_STEPS_POSITIONS_ERROR_CODE }
|
||||
}
|
||||
),
|
||||
GAP_BETWEEN_STEPS_POSITIONS_ERROR_CODE
|
||||
)
|
||||
}
|
||||
|
||||
private fun withSteps(steps: MutableSet<RecipeStep>, test: RecipeGroupInformation.() -> Unit) {
|
||||
private fun withGroupInformation(steps: MutableSet<RecipeStep>? = null, test: RecipeGroupInformation.() -> Unit) {
|
||||
recipeGroupInformation(
|
||||
group = employeeGroup(id = 0L),
|
||||
steps = steps
|
||||
steps = steps ?: mutableSetOf(
|
||||
recipeStep(id = 0L, position = 1),
|
||||
recipeStep(id = 1L, position = 2),
|
||||
recipeStep(id = 2L, position = 3),
|
||||
recipeStep(id = 3L, position = 4)
|
||||
)
|
||||
) {
|
||||
test()
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertInvalidStepsPositionsException(steps: MutableSet<RecipeStep>, errorType: String) {
|
||||
val exception = assertThrows<InvalidStepsPositionsException> {
|
||||
service.validateSteps(steps)
|
||||
}
|
||||
|
||||
assertTrue { exception.errors.size == 1 }
|
||||
assertTrue { exception.errors.first().type == errorType }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue