diff --git a/src/content.rs b/src/content.rs index 4c0070e..f79a4ff 100644 --- a/src/content.rs +++ b/src/content.rs @@ -1119,13 +1119,18 @@ pub fn validate_questions( a }; let _ = probe; - match resolve_question(questions, &filled) { - Some(target) if target.is_dynamic() => continue, - _ => anyhow::bail!( - "question {:?} alternative {:?}: templated action {:?} must land on a dynamic page ([name].yaml)", - question.id, alternative.name, action - ), + // Match the pattern itself: resolve_question would + // hand back a clone whose id is already concrete. + let lands = questions + .values() + .any(|q| q.is_dynamic() && path_matches(&q.id, &filled).is_some()); + if lands { + continue; } + anyhow::bail!( + "question {:?} alternative {:?}: templated action {:?} must land on a dynamic page ([name].yaml)", + question.id, alternative.name, action + ); } match questions.get(action) { None => anyhow::bail!( @@ -2025,6 +2030,22 @@ alternatives: assert_eq!(render_inline_markdown("[mail](mailto:bl@uhhm.no)"), "mail"); } + #[test] + fn templated_action_validates_against_the_dynamic_page() { + let landing: Question = serde_yaml::from_str( + "id: /\nname: L\nalternatives:\n - name: A\n action: /shape/{curve.key}\n", + ) + .unwrap(); + let place: Question = serde_yaml::from_str("id: /shape/[key]\nname: P\n").unwrap(); + let mut qs = std::collections::HashMap::new(); + qs.insert(landing.id.clone(), landing.clone()); + qs.insert(place.id.clone(), place); + validate_questions(&qs, &Default::default()).unwrap(); + let mut only_landing = std::collections::HashMap::new(); + only_landing.insert(landing.id.clone(), landing); + assert!(validate_questions(&only_landing, &Default::default()).is_err()); + } + #[test] fn action_templates_from_responses() { let r = serde_json::json!({"curve": {"key": "20aa98", "points": [[0,0]]}, "n": 3});