Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions crates/rustmotion-cli/src/commands/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,21 @@ impl ValidationReport {
/// every caller blocks on them without extra wiring); the direct
/// `attr_warnings` check below is defence in depth for a
/// `ValidationReport` assembled some other way.
///
/// `unresolved_vars` is deliberately **not** blocking. `variables.rs`
/// (constat #7) settled that a leftover `$word` cannot be told apart from
/// legitimate literal `$` content — a price tag, a terminal `$PATH` — so it
/// is reported as a loud warning and the document renders. Blocking here
/// contradicted that: `validate` printed "Valid scenario" and exited 0 on a
/// file `render` then refused, while the refusal told the user to run
/// `validate` for details it would never print. A declared variable can
/// never be left unresolved (every name in `defs` is present in
/// defaults ∪ overrides), and a `for-each`/`use` mistake is caught by name
/// in `expand.rs` — so nothing that reaches here is a diagnosable typo.
pub fn is_blocking(&self, lenient: bool) -> bool {
if !self.schema_errors.is_empty() {
return true;
}
if !self.unresolved_vars.is_empty() {
return true;
}
if !self.attr_warnings.is_empty() {
return true;
}
Expand Down Expand Up @@ -396,6 +404,38 @@ mod html_css_error_tests {
assert!(report.is_blocking(false), "must block rendering");
}

/// `validate` and `render` must agree. A leftover `$word` is a warning by
/// design (variables.rs, constat #7: a price tag or a `$PATH` is
/// indistinguishable from a typo), and `validate` treated it that way —
/// but `is_blocking` did not, so the same file passed validation and was
/// refused at render, with the refusal pointing back at validate.
#[test]
fn an_unresolved_variable_warns_without_blocking() {
let json = r##"{
"version": "1.0",
"video": {"width": 320, "height": 180, "fps": 30, "background": "#000"},
"scenes": [{"duration": 1.0, "children": [
{"type": "text", "content": "$9.99 a month",
"style": {"font-size": 20, "color": "#FFF"}}]}]
}"##;
let loaded = load(ValidationSource::Inline(json)).expect("loads");
let report = run_checks(&loaded, false);

assert!(
!report.unresolved_vars.is_empty(),
"a literal `$` must still be reported: {:?}",
report.unresolved_vars
);
assert!(
!report.is_blocking(false),
"a literal `$` in content must not stop the render"
);
assert!(
!report.is_clean(),
"it is still an advisory — is_clean must stay false so it gets printed"
);
}

#[test]
fn unknown_animation_preset_from_html_is_a_blocking_error() {
// Unknown preset names are not validated in the transpiler (no schema
Expand Down
Loading