prosaic_project/
fixture.rs1use prosaic_core::{Context, Value};
6use serde_json::Value as JsonValue;
7
8use crate::error::ProjectError;
9
10pub fn parse_fixture(name: &str, json: &str) -> Result<Context, ProjectError> {
12 let v: JsonValue = serde_json::from_str(json).map_err(|e| ProjectError::JsonParse {
13 file: name.to_string(),
14 cause: e.to_string(),
15 })?;
16 let obj = v
17 .as_object()
18 .ok_or_else(|| ProjectError::FixtureValidation {
19 name: name.to_string(),
20 reason: "fixture must be a JSON object".to_string(),
21 })?;
22 let mut ctx = Context::new();
23 for (k, v) in obj {
24 ctx.insert(k.clone(), json_to_value(v));
25 }
26 Ok(ctx)
27}
28
29fn json_to_value(v: &JsonValue) -> Value {
30 match v {
31 JsonValue::Null => Value::String(String::new()),
32 JsonValue::Bool(b) => Value::Number(if *b { 1 } else { 0 }),
33 JsonValue::Number(n) => {
34 if let Some(i) = n.as_i64() {
35 Value::Number(i)
36 } else if let Some(f) = n.as_f64() {
37 Value::Number(f as i64)
38 } else {
39 Value::Number(0)
40 }
41 }
42 JsonValue::String(s) => Value::String(s.clone()),
43 JsonValue::Array(items) => Value::List(
44 items
45 .iter()
46 .map(|i| match i {
47 JsonValue::String(s) => s.clone(),
48 other => other.to_string(),
49 })
50 .collect(),
51 ),
52 JsonValue::Object(_) => Value::String(v.to_string()),
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn parse_simple_fixture() {
62 let json = r#"{"name": "UserService", "entity_type": "class", "consumer_count": 6}"#;
63 let ctx = parse_fixture("test", json).unwrap();
64 assert_eq!(ctx.get("name").unwrap().as_display(), "UserService");
65 assert_eq!(ctx.get("consumer_count").unwrap().as_number().unwrap(), 6);
66 }
67
68 #[test]
69 fn parse_fixture_with_array() {
70 let json = r#"{"consumers": ["A", "B", "C"]}"#;
71 let ctx = parse_fixture("test", json).unwrap();
72 let list = ctx.get("consumers").unwrap().as_list().unwrap();
73 assert_eq!(
74 list,
75 vec!["A".to_string(), "B".to_string(), "C".to_string()]
76 );
77 }
78
79 #[test]
80 fn invalid_json_errors() {
81 let res = parse_fixture("bad", "{not json");
82 assert!(matches!(res, Err(ProjectError::JsonParse { .. })));
83 }
84
85 #[test]
86 fn non_object_errors() {
87 let res = parse_fixture("bad", "[1, 2, 3]");
88 assert!(matches!(res, Err(ProjectError::FixtureValidation { .. })));
89 }
90}