-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add subclass validation: ifInstanceOf and requireInstanceOf (#152)
- Loading branch information
1 parent
f5b0a7c
commit 115d231
Showing
6 changed files
with
209 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/commonMain/kotlin/io/konform/validation/string/ValidationBuilderString.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package io.konform.validation.string | ||
|
||
import io.konform.validation.Constraint | ||
import io.konform.validation.ValidationBuilder | ||
|
||
public fun ValidationBuilder<String>.notBlank(): Constraint<String> = addConstraint("must not be blank") { it.isNotBlank() } |
37 changes: 37 additions & 0 deletions
37
src/commonMain/kotlin/io/konform/validation/validations/IsClassValidation.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package io.konform.validation.validations | ||
|
||
import io.konform.validation.Invalid | ||
import io.konform.validation.Valid | ||
import io.konform.validation.Validation | ||
import io.konform.validation.ValidationResult | ||
import kotlin.reflect.KClass | ||
import kotlin.reflect.safeCast | ||
|
||
/** | ||
* Can run a validation if the input is of a specific type. | ||
* @param clazz Class tag for the type | ||
* @param required If true, will give an error if the actual input is not of the type. | ||
* If false, will do nothing for a different type. | ||
* @param validation The validation to run for the type | ||
* @param T The type that the input must be of | ||
* @param ParentT The best-defined parent type of T | ||
*/ | ||
public class IsClassValidation<T : ParentT & Any, ParentT>( | ||
private val clazz: KClass<T>, | ||
private val required: Boolean = false, | ||
private val validation: Validation<T>, | ||
) : Validation<ParentT> { | ||
override fun validate(value: ParentT): ValidationResult<ParentT> { | ||
val castedValue = clazz.safeCast(value) | ||
return if (castedValue == null) { | ||
if (required) { | ||
val actualType = value?.let { it::class.simpleName } | ||
Invalid(mapOf("" to listOf("must be a '${clazz.simpleName}', was a '$actualType'"))) | ||
} else { | ||
Valid(value) | ||
} | ||
} else { | ||
validation.validate(castedValue) | ||
} | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
src/commonTest/kotlin/io/konform/validation/validationbuilder/InstanceOfTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package io.konform.validation.validationbuilder | ||
|
||
import io.konform.validation.PropertyValidationError | ||
import io.konform.validation.Validation | ||
import io.konform.validation.string.notBlank | ||
import io.kotest.assertions.konform.shouldBeInvalid | ||
import io.kotest.assertions.konform.shouldBeValid | ||
import io.kotest.assertions.konform.shouldContainExactlyErrors | ||
import kotlin.test.Test | ||
|
||
class InstanceOfTest { | ||
private val catValidation = | ||
Validation<Cat> { | ||
Cat::favoritePrey { | ||
notBlank() | ||
} | ||
} | ||
|
||
private val ifCatValidation = | ||
Validation<Animal?> { | ||
ifInstanceOf<Cat> { | ||
run(catValidation) | ||
} | ||
} | ||
|
||
private val requireCatValidation = | ||
Validation<Animal?> { | ||
requireInstanceOf<Cat> { | ||
run(catValidation) | ||
} | ||
} | ||
|
||
val validCat = Cat("cat", "mouse") | ||
val invalidCat = Cat("", "") | ||
val validDog = Dog("dog") | ||
val invalidDog = Dog("") | ||
|
||
@Test | ||
fun ifInstanceOfTest() { | ||
ifCatValidation shouldBeValid validCat | ||
ifCatValidation shouldBeValid validDog | ||
ifCatValidation shouldBeValid invalidDog | ||
ifCatValidation shouldBeValid null | ||
|
||
val invalid = ifCatValidation shouldBeInvalid invalidCat | ||
invalid shouldContainExactlyErrors | ||
listOf( | ||
PropertyValidationError(".favoritePrey", "must not be blank"), | ||
) | ||
} | ||
|
||
@Test | ||
fun requireInstanceOfTest() { | ||
requireCatValidation shouldBeValid validCat | ||
|
||
val invalidCatResult = requireCatValidation shouldBeInvalid invalidCat | ||
invalidCatResult shouldContainExactlyErrors | ||
listOf( | ||
PropertyValidationError(".favoritePrey", "must not be blank"), | ||
) | ||
|
||
val validDogResult = requireCatValidation shouldBeInvalid validDog | ||
val invalidDogResult = requireCatValidation shouldBeInvalid invalidDog | ||
val expectedError = | ||
listOf( | ||
PropertyValidationError("", "must be a 'Cat', was a 'Dog'"), | ||
) | ||
validDogResult shouldContainExactlyErrors expectedError | ||
invalidDogResult shouldContainExactlyErrors expectedError | ||
|
||
val nullResult = requireCatValidation shouldBeInvalid null | ||
nullResult shouldContainExactlyErrors | ||
listOf( | ||
PropertyValidationError("", "must be a 'Cat', was a 'null'"), | ||
) | ||
} | ||
} | ||
|
||
sealed interface Animal { | ||
val name: String | ||
} | ||
|
||
data class Cat( | ||
override val name: String, | ||
val favoritePrey: String, | ||
) : Animal | ||
|
||
data class Dog( | ||
override val name: String, | ||
) : Animal |