
DynamicMetadataTest.pudu
Pudu81 lines4.6 KB
1/** @Test.Validation.DynamicMetadata.Suite — checks source-derived failure fields */2module PuduLangValidator.DynamicMetadataTest34import Std.Test as Test5import PuduLangValidator.Async as Async6import PuduLangValidator.Result as Validation7import PuduLangValidator.Rule as Rule8import PuduLangValidator.Validator as Validator910type Model = { name: Str, priority: Int }1112fn syncRule() -> Rule.RuleBuilder[Model, Str] {13 let checked = Rule.must(Rule.ruleFor("name", |model: Model| model.name),14 |value: Str| value == "ok")15 let severity = Rule.withSeverityFrom(checked, fn(root: Model, _value: Str) -> Validation.Severity {16 if root.priority > 1 { Validation.Warning } else { Validation.Info }17 })18 Rule.withStateFrom(severity, fn(root: Model, value: Str) -> Str {19 value + ":" + show(root.priority)20 })21}2223async fn matches(_root: Model, value: Str) -> Bool { value == "ok" }2425fn asyncRule() -> Async.AsyncRule[Model] {26 let checked = Async.mustAsync("name", |model: Model| model.name, matches,27 "Name failed.", "Name")28 let severity = Async.withSeverityFrom(checked, fn(root: Model) -> Validation.Severity {29 if root.priority > 1 { Validation.Warning } else { Validation.Info }30 })31 Async.withStateFrom(severity, fn(root: Model) -> Str { root.name + ":" + show(root.priority) })32}3334async fn main() -> Int {35 let bad = Model{name: "bad", priority: 2}36 let good = Model{name: "ok", priority: 2}37 let sync = Validator.add(Validator.create(), Rule.build(syncRule()))38 let syncBad = Validator.validate(&sync, bad)39 let syncGood = Validator.validate(&sync, good)40 let staticLast = Rule.withState(Rule.withSeverity(syncRule(), Validation.Error), "fixed")41 let staticResult = Validator.validate(&Validator.add(Validator.create(), Rule.build(staticLast)), bad)42 let dynamicLast = Rule.withStateFrom(Rule.withSeverityFrom(43 Rule.withState(Rule.withSeverity(Rule.must(Rule.ruleFor("name", |model: Model| model.name),44 |_value: Str| false), Validation.Error), "fixed"),45 fn(_root: Model, _value: Str) -> Validation.Severity { Validation.Info }),46 fn(root: Model, _value: Str) -> Str { show(root.priority) })47 let dynamicResult = Validator.validate(&Validator.add(Validator.create(), Rule.build(dynamicLast)), bad)48 let awaited = Async.add(Async.create(), asyncRule())49 let asyncBad = Async.validateAsync(&awaited, bad).await50 let asyncGood = Async.validateAsync(&awaited, good).await51 let asyncStatic = Async.add(Async.create(),52 Async.withState(Async.withSeverity(asyncRule(), Validation.Error), "fixed"))53 let asyncStaticResult = Async.validateAsync(&asyncStatic, bad).await54 let overridden = Async.withState(Async.withSeverity(55 Async.withStateFrom(Async.withSeverityFrom(asyncRule(),56 fn(_root: Model) -> Validation.Severity { panic("overridden severity ran") }),57 fn(_root: Model) -> Str { panic("overridden state ran") }),58 Validation.Error), "fixed")59 let overriddenResult = Async.validateAsync(&Async.add(Async.create(), overridden), bad).await60 let skippedFactory = Async.withSeverityFrom(asyncRule(),61 fn(_root: Model) -> Validation.Severity { panic("successful rule computed severity") })62 let skippedResult = Async.validateAsync(&Async.add(Async.create(), skippedFactory), good).await63 let checks = Test.suite("DynamicMetadata", &[64 Test.equals("sync severity comes from root", &syncBad.errors[0].severity, &Validation.Warning),65 Test.equals("sync state sees root and property", &syncBad.errors[0].customState, &"bad:2"),66 Test.equals("successful sync check has no failure", &syncGood.errors.length(), &0),67 Test.equals("later static severity wins", &staticResult.errors[0].severity, &Validation.Error),68 Test.equals("later static state wins", &staticResult.errors[0].customState, &"fixed"),69 Test.equals("later computed severity wins", &dynamicResult.errors[0].severity, &Validation.Info),70 Test.equals("later computed state wins", &dynamicResult.errors[0].customState, &"2"),71 Test.equals("async severity comes from root", &asyncBad.errors[0].severity, &Validation.Warning),72 Test.equals("async state comes from root", &asyncBad.errors[0].customState, &"bad:2"),73 Test.equals("successful async check has no failure", &asyncGood.errors.length(), &0),74 Test.equals("outer static async severity wins", &asyncStaticResult.errors[0].severity, &Validation.Error),75 Test.equals("outer static async state wins", &asyncStaticResult.errors[0].customState, &"fixed"),76 Test.equals("overridden async callbacks are not run", &overriddenResult.errors[0].customState, &"fixed"),77 Test.equals("successful async rules skip metadata callbacks", &skippedResult.errors.length(), &0)78 ])79 Test.report(&Test.run(&checks))80}81