
Testing.pudu
Pudu118 lines4.9 KB
1/** @Validation.Testing.Predicates — queries structured validation results */2module PuduLangValidator.Testing34import Std.List as List5import PuduLangValidator.Async as Async6import PuduLangValidator.Result as Validation7import PuduLangValidator.Validator as Validator89/** @Validation.Testing.FailureQuery — narrows failures while retaining the full result */10export type FailureQuery = {11 all: Array[Validation.Failure],12 matched: Array[Validation.Failure]13}141516export fn testValidate[T](validator: &Validator.Validator[T], root: T) -> Validation.ValidationResult {17 Validator.validate(validator, root)18}192021export fn testValidateWith[T](22 validator: &Validator.Validator[T], root: T, options: Validator.Options23) -> Validation.ValidationResult {24 Validator.validateWith(validator, root, options)25}262728export async fn testValidateAsync[T](29 validator: &Async.AsyncValidator[T], root: T30) -> Validation.ValidationResult {31 Async.validateAsync(validator, root).await32}333435export async fn testValidateAsyncWith[T](36 validator: &Async.AsyncValidator[T], root: T, options: Validator.Options37) -> Validation.ValidationResult {38 Async.validateAsyncWith(validator, root, options).await39}404142export fn forProperty(result: &Validation.ValidationResult, path: Str) -> FailureQuery {43 FailureQuery{all: result.errors,44 matched: result.errors.filter(|failure: Validation.Failure| failure.propertyName == path) }45}464748export fn withMessage(query: FailureQuery, message: Str) -> FailureQuery {49 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.errorMessage == message)}50}515253export fn withoutMessage(query: FailureQuery, message: Str) -> FailureQuery {54 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.errorMessage != message)}55}565758export fn withCode(query: FailureQuery, code: Str) -> FailureQuery {59 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.errorCode == code)}60}616263export fn withoutCode(query: FailureQuery, code: Str) -> FailureQuery {64 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.errorCode != code)}65}666768export fn withSeverity(query: FailureQuery, severity: Validation.Severity) -> FailureQuery {69 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.severity == severity)}70}717273export fn withoutSeverity(query: FailureQuery, severity: Validation.Severity) -> FailureQuery {74 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.severity != severity)}75}767778export fn withState(query: FailureQuery, state: Str) -> FailureQuery {79 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.customState == state)}80}818283export fn withoutState(query: FailureQuery, state: Str) -> FailureQuery {84 FailureQuery{..query, matched: query.matched.filter(|failure: Validation.Failure| failure.customState != state)}85}868788export fn hasAny(query: &FailureQuery) -> Bool { !query.matched.isEmpty() }899091export fn hasNone(query: &FailureQuery) -> Bool { query.matched.isEmpty() }929394export fn only(query: &FailureQuery) -> Bool {95 !query.matched.isEmpty() && query.matched.length() == query.all.length()96}979899export fn hasErrorFor(result: &Validation.ValidationResult, path: Str) -> Bool {100 List.any(&result.errors, |failure: Validation.Failure| failure.propertyName == path)101}102103104export fn hasNoErrorFor(result: &Validation.ValidationResult, path: Str) -> Bool {105 !hasErrorFor(result, path)106}107108109export fn hasCode(result: &Validation.ValidationResult, code: Str) -> Bool {110 List.any(&result.errors, |failure: Validation.Failure| failure.errorCode == code)111}112113114export fn onlyErrorsFor(result: &Validation.ValidationResult, paths: Array[Str]) -> Bool {115 !result.errors.isEmpty() && List.all(&result.errors,116 |failure: Validation.Failure| paths.contains(failure.propertyName))117}118