#![allow(clippy::float_cmp)] use assemblage_db::{ data::{Id, Layout, Node}, tx, Db, Result, }; use assemblage_kv::test; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); test! { async fn overlap_after_swap(storage) -> Result<()> { let db = Db::open(storage).await?; let foo_id = tx!(|db| db.add(Node::text("This is a sentence containing foo")).await?); let bar_id = tx!(|db| db.add(Node::text("This is a sentence containing bar")).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); tx!(|db| db.swap(foo_id, Node::text("something completely different")).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.swap(foo_id, Node::text("sentence containing foo")).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn overlap_after_swap_of_nested_child(storage) -> Result<()> { let db = Db::open(storage).await?; let text_foo_id = tx!(|db| db.add(Node::text("This is a sentence containing foo")).await?); let text_bar_id = tx!(|db| db.add(Node::text("This is a sentence containing bar")).await?); let foo_id = tx!(|db| db.add(Node::list(Layout::Chain, vec![text_foo_id])).await?); let bar_id = tx!(|db| db.add(Node::list(Layout::Chain, vec![text_bar_id])).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); tx!(|db| db.swap(foo_id, Node::text("something completely different")).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.swap(foo_id, Node::text("sentence containing foo")).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn overlap_after_push(storage) -> Result<()> { let db = Db::open(storage).await?; let foo_id = tx!(|db| db.add(Node::list(Layout::Chain, vec![ Node::text("Thi"), ])).await?); let bar_id = tx!(|db| db.add(Node::text("This is a sentence about bar")).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.push(foo_id, Node::text("s a sentence about foo")).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn overlap_after_remove(storage) -> Result<()> { let db = Db::open(storage).await?; let foo_id = tx!(|db| db.add(Node::list(Layout::Chain, vec![ Node::text("foo"), Node::text("bar"), Node::text("baz"), Node::text("qux"), ])).await?); let bar_id = tx!(|db| db.add(Node::text("just fooqux")).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.remove(foo_id, 2).await?); tx!(|db| db.remove(foo_id, 1).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn overlap_after_replacing_empty_text(storage) -> Result<()> { let db = Db::open(storage).await?; let shared_text = "This is a sentence about something"; let foo_id = tx!(|db| db.add(Node::text("")).await?); let bar_id = tx!(|db| db.add(Node::text("")).await?); let page_foo_id = tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); let page_bar_id = tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.replace(page_foo_id, 0, Node::text(shared_text)).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text(shared_text)).await?); let foo_id = tx!(|db| db.get(page_foo_id).await?.unwrap().children()[0].id()?); let bar_id = tx!(|db| db.get(page_bar_id).await?.unwrap().children()[0].id()?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn overlap_after_incrementally_replacing_text(storage) -> Result<()> { let db = Db::open(storage).await?; let foo_id = tx!(|db| db.add(Node::text("")).await?); let bar_id = tx!(|db| db.add(Node::text("")).await?); let page_foo_id = tx!(|db| db.add(Node::list(Layout::Page, vec![foo_id])).await?); let page_bar_id = tx!(|db| db.add(Node::list(Layout::Page, vec![bar_id])).await?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 0); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 0); tx!(|db| db.replace(page_foo_id, 0, Node::text("This")).await?); tx!(|db| db.replace(page_foo_id, 0, Node::text("This is")).await?); tx!(|db| db.replace(page_foo_id, 0, Node::text("This is another")).await?); tx!(|db| db.replace(page_foo_id, 0, Node::text("This is another sentence")).await?); tx!(|db| db.replace(page_foo_id, 0, Node::text("This is another sentence about")).await?); tx!(|db| db.replace(page_foo_id, 0, Node::text("This is another sentence about foo")).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text("Just")).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text("Just another")).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text("Just another sentence")).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text("Just another sentence about")).await?); tx!(|db| db.replace(page_bar_id, 0, Node::text("Just another sentence about bar")).await?); let foo_id = tx!(|db| db.get(page_foo_id).await?.unwrap().children()[0].id()?); let bar_id = tx!(|db| db.get(page_bar_id).await?.unwrap().children()[0].id()?); assert_eq!(db.current().await.overlaps(foo_id).await?.len(), 1); assert_eq!(db.current().await.overlaps(bar_id).await?.len(), 1); } } test! { async fn no_overlap_between_ancestor_and_child_after_replace(storage) -> Result<()> { let db = Db::open(storage).await?; let ancestor_page_id = tx!(|db| db.add(Node::list(Layout::Page, vec![ Node::list(Layout::Page, vec![Node::text("")]), ])).await?); let text1_id = tx!(|db| db.add(Node::text("some text")).await?); let page_id = tx!(|db| db.add(Node::list(Layout::Page, vec![text1_id])).await?); tx!(|db| db.insert(ancestor_page_id, 0, page_id).await?); assert_eq!(db.current().await.overlaps(text1_id).await?.len(), 0); let text2_id = tx!(|db| db.add(Node::text("some text")).await?); tx!(|db| db.remove(page_id, 0).await?); tx!(|db| db.insert(page_id, 0, text2_id).await?); } } test! { async fn overlaps_after_restoring_node(storage) -> Result<()> { let db = Db::open(storage).await?; let text1_id = tx!(|db| { db.add(Node::text("this should be found as an overlap")).await? }); let text2_id = tx!(|db| { db.add(Node::text("this should be found as an overlap...")).await? }); let page1_id = tx!(|db| { db.add(Node::list(Layout::Page, vec![text1_id])).await? }); tx!(|db| db.push(Id::root(), page1_id).await?); tx!(|db| db.add(Node::list(Layout::Page, vec![text2_id])).await?); tx!(|db| { assert_eq!(db.overlaps(text1_id).await?.len(), 1); assert_eq!(db.overlaps(text1_id).await?[0].id, text2_id); assert_eq!(db.overlaps(text2_id).await?.len(), 1); assert_eq!(db.overlaps(text2_id).await?[0].id, text1_id); }); tx!(|db| db.remove(Id::root(), 0).await?); tx!(|db| { assert_eq!(db.get(text1_id).await?, None); assert_eq!(db.overlaps(text2_id).await?.len(), 0); assert!(db.overlaps(text1_id).await.is_err()); }); tx!(|db| db.restore(page1_id).await?); tx!(|db| { assert!(db.get(text1_id).await?.is_some()); assert_eq!(db.overlaps(text1_id).await?.len(), 1); assert_eq!(db.overlaps(text1_id).await?[0].id, text2_id); assert_eq!(db.overlaps(text2_id).await?.len(), 1); assert_eq!(db.overlaps(text2_id).await?[0].id, text1_id); }); } }