#![cfg(feature = "assemblage-broadcast-integration-tests")]
use assemblage_db::{
broadcast::Broadcast,
data::{Id, Layout, Node},
tx, Db,
};
use assemblage_kv::{storage::MemoryStorage, test};
use assemblage_view::{
model::{Block, Section, Span, Subsection, Tile},
DbView, Result,
};
use std::{collections::BTreeSet, iter::FromIterator};
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
test! {
async fn broadcast_tile(storage) -> Result<()> {
let db = Db::open(storage).await?;
let root_id = Id::root();
let (id1, id2, broadcast, last_updated) = {
let text1 = Node::text("foo");
let id1 = tx!(|db| db.add(text1).await?);
tx!(|db| db.push(root_id, id1).await?);
tx!(|db| assert_eq!(db.get(id1).await?.unwrap().str()?, "foo"));
let text2 = Node::text("foobar");
let id2 = tx!(|db| db.add(text2).await?);
tx!(|db| db.push(root_id, id2).await?);
tx!(|db| assert_eq!(db.get(id2).await?.unwrap().str()?, "foobar"));
let last_updated = tx!(|db| db.last_updated().await?.unwrap());
let broadcast = tx!(|db| db.publish_broadcast(root_id).await?);
(id1, id2, broadcast, last_updated)
};
assert!(broadcast.expiration.unwrap_or_default() >= last_updated + 60 * 60 * 24);
let mut current = db.current().await;
let tile = current.tile(root_id).await?;
let expected = Tile {
id: root_id,
preview: Block::Text {
styles: BTreeSet::new(),
spans: vec![
Span::Text {
styles: BTreeSet::new(),
text: "foo".to_string(),
}
]
},
broadcasts: BTreeSet::from_iter(vec![
Broadcast {
broadcast_id: broadcast.broadcast_id.clone(),
node_id: root_id,
last_updated,
expiration: broadcast.expiration,
}
]),
sections: vec![
Section {
id: None,
has_multiple_parents: false,
subsections: vec![
Subsection {
id: id1,
block: Block::Text {
styles: BTreeSet::new(),
spans: vec![
Span::Text {
styles: BTreeSet::new(),
text: "foo".to_string(),
}
]
},
before: vec![],
after: vec![],
}
]
},
Section {
id: None,
has_multiple_parents: false,
subsections: vec![
Subsection {
id: id2,
block: Block::Text {
styles: BTreeSet::new(),
spans: vec![
Span::Text {
styles: BTreeSet::new(),
text: "foobar".to_string(),
}
]
},
before: vec![],
after: vec![],
}
]
}
],
branches: vec![],
};
assert_eq!(tile, expected);
let storage = MemoryStorage::new();
let other = Db::open(storage).await?;
let mut current = other.current().await;
let other_tile = current.tile_from_broadcast(&broadcast.broadcast_id).await?;
let namespaced = current.namespaced_id(&broadcast.broadcast_id.into(), root_id).await?;
assert_eq!(other_tile.id, namespaced);
assert_eq!(other_tile.preview, expected.preview);
assert_eq!(other_tile.broadcasts, BTreeSet::new());
assert_eq!(other_tile.branches, expected.branches);
assert_eq!(other_tile.sections.len(), expected.sections.len());
for (mut found, mut expected) in other_tile.sections.into_iter().zip(expected.sections) {
assert_eq!(found.id, None);
assert_eq!(expected.id, None);
for (found, expected) in found.subsections.iter_mut().zip(expected.subsections.iter_mut()) {
let found_id = std::mem::replace(&mut found.id, Id::root());
let expected_id = std::mem::replace(&mut expected.id, Id::root());
let namespaced = current.namespaced_id(&broadcast.broadcast_id.into(), expected_id).await?;
assert_eq!(found_id, namespaced);
}
assert_eq!(found, expected);
}
}
}
test! {
async fn multi_broadcast_tile(storage) -> Result<()> {
let db = Db::open(storage).await?;
let root_id = Id::root();
let (id2, broadcast1, last_updated1, broadcast2, last_updated2) = {
let text1 = Node::text("foo");
let id1 = tx!(|db| db.add(text1).await?);
tx!(|db| db.push(root_id, id1).await?);
let text2 = Node::text("foobar");
let id2 = tx!(|db| db.add(Node::list(Layout::Page, vec![text2])).await?);
tx!(|db| db.push(root_id, id2).await?);
let last_updated1 = tx!(|db| db.last_updated().await?.unwrap());
let broadcast1 = tx!(|db| db.publish_broadcast(root_id).await?);
let last_updated2 = tx!(|db| db.last_updated().await?.unwrap());
let broadcast2 = tx!(|db| db.publish_broadcast(id2).await?);
(id2, broadcast1, last_updated1, broadcast2, last_updated2)
};
let mut current = db.current().await;
let tile = current.tile(root_id).await?;
assert_eq!(tile.broadcasts, BTreeSet::from_iter(vec![
Broadcast {
broadcast_id: broadcast1.broadcast_id.clone(),
node_id: root_id,
last_updated: last_updated1,
expiration: broadcast1.expiration,
}
]));
let tile = current.tile(id2).await?;
assert_eq!(tile.broadcasts, BTreeSet::from_iter(vec![
Broadcast {
broadcast_id: broadcast2.broadcast_id.clone(),
node_id: id2,
last_updated: last_updated2,
expiration: broadcast2.expiration,
},
Broadcast {
broadcast_id: broadcast1.broadcast_id.clone(),
node_id: root_id,
last_updated: last_updated1,
expiration: broadcast1.expiration,
}
]));
let storage = MemoryStorage::new();
let other = Db::open(storage).await?;
let mut current = other.current().await;
let broadcast1_id = broadcast1.broadcast_id;
let broadcast2_id = broadcast2.broadcast_id;
let other_tile = current.tile_from_broadcast(&broadcast1_id).await?;
let namespaced_root_id1 = current.namespaced_id(&broadcast1_id, root_id).await?;
assert_eq!(other_tile.id, namespaced_root_id1);
assert_eq!(other_tile.broadcasts, BTreeSet::new());
let other_tile = current.tile_from_broadcast(&broadcast2_id).await?;
let namespaced_root_id2 = current.namespaced_id(&broadcast2_id, root_id).await?;
assert_eq!(other_tile.id, namespaced_root_id2);
assert_eq!(other_tile.broadcasts, BTreeSet::new());
assert_eq!(other_tile.branches, vec![]);
assert_eq!(other_tile.sections.len(), 1);
assert_eq!(other_tile.sections[0].subsections.len(), 1);
let other_tile_root_sections = other_tile.sections;
let namespaced = current.namespaced_id(&broadcast2_id, id2).await?;
let other_tile = current.tile(namespaced).await?;
assert_eq!(other_tile.id, namespaced);
assert_eq!(other_tile.broadcasts, BTreeSet::new());
assert_eq!(other_tile.branches, vec![]);
assert_eq!(other_tile.sections.len(), 1);
assert_eq!(other_tile.sections[0].subsections.len(), 1);
assert_eq!(
other_tile_root_sections[0].subsections[0],
other_tile.sections[0].subsections[0]
);
}
}