use loro::{LoroDoc, LoroList, LoroMap, LoroValue, ToJson, ValueOrContainer}; use serde_json::json; fn to_json(v: Vec) -> serde_json::Value { v.into_iter() .map(|x| x.get_deep_value().to_json_value()) .collect() } fn create_map_from_json(json: serde_json::Value) -> LoroMap { let map = LoroMap::new(); for (key, value) in json.as_object().unwrap().iter() { map.insert(key, value.clone()).unwrap(); } map } fn setup_test_doc() -> LoroDoc { let doc = LoroDoc::new(); let store = doc.get_map("store"); let books = store.insert_container("book", LoroList::new()).unwrap(); books .insert_container( 0, create_map_from_json(json!({ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95, "isbn": "0-553-21311-3" })), ) .unwrap(); books .insert_container( 1, create_map_from_json(json!({ "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, "isbn": "0-553-21312-1" })), ) .unwrap(); books .insert_container( 2, create_map_from_json(json!({ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "price": 8.99, "isbn": "0-553-21313-X" })), ) .unwrap(); books .insert_container( 3, create_map_from_json(json!({ "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "price": 22.99, "isbn": "0-395-19395-8" })), ) .unwrap(); store .insert_container( "bicycle", create_map_from_json(json!({ "color": "red", "price": 19.95 })), ) .unwrap(); store.insert("expensive", 10).unwrap(); doc } #[test] fn test_all_authors() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$.store.book[*].author")?; assert_eq!( to_json(ans), json!([ "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" ]) ); Ok(()) } #[test] #[ignore = "filter syntax not implemented"] fn test_books_with_isbn() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[?(@.isbn)]")?; assert_eq!(ans.len(), 4); Ok(()) } #[test] fn test_all_things_in_store() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$.store.*")?; assert_eq!(ans.len(), 3); // book array, bicycle object, and expensive value Ok(()) } #[test] fn test_all_authors_recursive() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..author")?; assert_eq!( to_json(ans), json!([ "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" ]) ); Ok(()) } #[test] fn test_all_prices() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$.store..price")?; assert_eq!(to_json(ans), json!([19.95, 8.95, 12.99, 8.99, 22.99])); Ok(()) } #[test] fn test_third_book() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[2]")?; assert_eq!( to_json(ans), json!([{ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "price": 8.99, "isbn": "0-553-21313-X" }]) ); Ok(()) } #[test] fn test_second_to_last_book() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[-2]")?; assert_eq!( to_json(ans), json!([{ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "price": 8.99, "isbn": "0-553-21313-X" }]) ); Ok(()) } #[test] fn test_first_two_books() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[0,1]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] fn test_books_slice() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[:2]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] fn test_books_slice_from_index() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[1:2]")?; assert_eq!(ans.len(), 1); Ok(()) } #[test] fn test_last_two_books() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[-2:]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] fn test_book_number_two_from_tail() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[2:]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] #[ignore = "filter syntax not implemented"] fn test_books_cheaper_than_10() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$.store.book[?(@.price < 10)]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] #[ignore = "filter syntax not implemented"] fn test_books_not_expensive() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[?(@.price <= $.expensive)]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] fn test_everything() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..*")?; assert!(!ans.is_empty()); Ok(()) } #[test] fn test_books_slice_with_step() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$..book[1:9:3]")?; assert_eq!(ans.len(), 1); Ok(()) } #[test] fn test_multiple_keys() -> anyhow::Result<()> { let doc = setup_test_doc(); let ans = doc.jsonpath("$.store[\"book\", \"bicycle\"]")?; assert_eq!(ans.len(), 2); Ok(()) } #[test] fn test_jsonpath() -> anyhow::Result<()> { let doc = LoroDoc::new(); doc.get_map("root").insert("key", LoroValue::from(1))?; doc.get_map("root").insert("key2", LoroValue::from(2))?; doc.get_map("root").insert("key3", LoroValue::from(3))?; let ans = doc.jsonpath("$..").unwrap(); assert_eq!( to_json(ans), serde_json::json!([ 1, 2, 3, { "key": 1, "key2": 2, "key3": 3 }, { "root": { "key": 1, "key2": 2, "key3": 3 } } ]) ); Ok(()) } #[test] fn test_jsonpath_with_array() -> anyhow::Result<()> { let doc = LoroDoc::new(); let array = doc.get_list("root"); array.insert(0, 1)?; array.insert(1, 2)?; array.insert(2, 3)?; let ans = doc.jsonpath("$..")?; assert_eq!( to_json(ans), serde_json::json!([ 1, 2, 3, [1, 2, 3], { "root": [1, 2, 3] } ]) ); Ok(()) } #[test] fn test_jsonpath_nested_objects() -> anyhow::Result<()> { let doc = LoroDoc::new(); let root = doc.get_map("root"); let child = root.insert_container("child", LoroMap::new())?; child.insert("key", "value")?; let ans = doc.jsonpath("$.root.child.key").unwrap(); assert_eq!(to_json(ans), serde_json::json!(["value"])); Ok(()) } #[test] fn test_jsonpath_wildcard() -> anyhow::Result<()> { let doc = LoroDoc::new(); let root = doc.get_map("root"); root.insert("key1", 1)?; root.insert("key2", 2)?; root.insert("key3", 3)?; let ans = doc.jsonpath("$.root.*").unwrap(); assert_eq!(to_json(ans), serde_json::json!([1, 2, 3])); Ok(()) }