AppFlowy-Cloud/tests/collab_history/document_history.rs

121 lines
3.6 KiB
Rust

use assert_json_diff::assert_json_include;
use client_api_test::TestClient;
use collab::core::collab::DataSource;
use collab::core::origin::CollabOrigin;
use collab::preclude::updates::decoder::Decode;
use collab::preclude::updates::encoder::{Encoder, EncoderV2};
use collab::preclude::{Collab, ReadTxn, Snapshot, Update};
use collab_entity::CollabType;
use serde_json::json;
use tokio::time::sleep;
#[tokio::test]
async fn collab_history_and_snapshot_test() {
let mut test_client = TestClient::new_user().await;
let workspace_id = test_client.workspace_id().await;
let object_id = uuid::Uuid::new_v4().to_string();
// Using [CollabType::Unknown] for testing purposes.
let collab_type = CollabType::Unknown;
test_client
.create_and_edit_collab_with_data(&object_id, &workspace_id, collab_type.clone(), None)
.await;
test_client
.open_collab(&workspace_id, &object_id, collab_type.clone())
.await;
// from the beginning, there should be no snapshots
let snapshots = test_client
.api_client
.get_snapshots(&workspace_id, &object_id, collab_type.clone())
.await
.unwrap()
.items;
assert!(snapshots.is_empty());
// Simulate the client editing the collaboration object. A snapshot is generated if the number of edits
// exceeds a specific threshold. By default, [CollabType::Unknown] has a threshold of 10 edits in debug mode.
for i in 0..10 {
let mut lock = test_client
.collabs
.get(&object_id)
.unwrap()
.collab
.write()
.await;
lock.borrow_mut().insert(&i.to_string(), i.to_string());
sleep(std::time::Duration::from_millis(1000)).await;
}
// Wait for the snapshot to be generated.
sleep(std::time::Duration::from_secs(10)).await;
let snapshots = test_client
.api_client
.get_snapshots(&workspace_id, &object_id, collab_type.clone())
.await
.unwrap()
.items;
assert!(!snapshots.is_empty());
// Get the latest history
let snapshot_info = test_client
.api_client
.get_latest_history(&workspace_id, &object_id, collab_type)
.await
.unwrap();
let full_collab = Collab::new_with_source(
CollabOrigin::Empty,
&object_id,
DataSource::DocStateV2(snapshot_info.history.doc_state),
vec![],
true,
)
.unwrap();
// Collab restored from the history data may not contain all the data. So just compare part of the data.
assert_json_include!(
actual: full_collab.to_json_value(),
expected: json!({
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
})
);
// Collab restored from snapshot data might equal to full_collab or be a subset of full_collab.
let snapshot = Snapshot::decode_v1(snapshot_info.snapshot_meta.snapshot.as_slice()).unwrap();
let snapshot_collab = get_snapshot_collab(&full_collab, &snapshot, &object_id);
let snapshot_json = snapshot_collab.to_json_value();
assert_json_include!(
actual: snapshot_json,
expected: json!({
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
})
);
}
pub fn get_snapshot_collab(collab: &Collab, snapshot: &Snapshot, object_id: &str) -> Collab {
let txn = collab.transact();
let mut encoder = EncoderV2::new();
collab
.transact()
.encode_state_from_snapshot(snapshot, &mut encoder)
.unwrap();
let update = Update::decode_v2(&encoder.to_vec()).unwrap();
drop(txn);
let mut collab = Collab::new_with_origin(CollabOrigin::Empty, object_id, vec![], false);
let mut txn = collab.transact_mut();
txn.apply_update(update).unwrap();
drop(txn);
collab
}