use std::path::Path;
use camel_integration_test::ScenarioDocument;
use noyalib::compat::serde_yaml;
use super::parse_test_document;
use super::{BODY_SCALAR_SENTINEL, MATCHER_SENTINEL, TestDocError, TestDocument};
pub(crate) enum ParsedDocument {
Unit(Box<TestDocument>),
Scenario(Box<ScenarioDocument>),
}
fn declares_execute(text: &str) -> bool {
serde_yaml::from_str::<serde_yaml::Value>(text)
.ok()
.and_then(|value| value.get("execute").map(|_| true))
.unwrap_or(false)
}
fn declares_scenario(text: &str) -> bool {
serde_yaml::from_str::<serde_yaml::Value>(text)
.ok()
.and_then(|value| value.get("scenario").map(|_| true))
.unwrap_or(false)
}
pub(crate) fn parse_document(path: &Path, text: &str) -> Result<ParsedDocument, String> {
if declares_execute(text) {
Err(format!(
"{}: document declares an execute: section (the `camel job` vocabulary); \
camel test does not run job documents",
path.display()
))
} else if declares_scenario(text) {
camel_integration_test::parse_scenario_document(path)
.map(|scenario| ParsedDocument::Scenario(Box::new(scenario)))
.map_err(|e| e.to_string())
} else {
parse_test_document(text)
.map(|doc| ParsedDocument::Unit(Box::new(doc)))
.map_err(|e| e.to_string())
}
}
pub(super) fn classify_yaml_error(raw: &str) -> TestDocError {
if let Some((_, after)) = raw.split_once(BODY_SCALAR_SENTINEL) {
let scalar = after.split_whitespace().next().unwrap_or_default();
return TestDocError::UnsupportedBodyScalar(scalar.to_string());
}
if let Some((_, after)) = raw.split_once(MATCHER_SENTINEL) {
let msg = after.split_once(" at line ").map_or(after, |(msg, _)| msg);
return TestDocError::InvalidMatcher(msg.to_string());
}
if raw.contains("unknown field") {
return TestDocError::UnknownField(raw.to_string());
}
TestDocError::Yaml(raw.to_string())
}