automorph 0.2.0

Derive macros for bidirectional Automerge-Rust struct synchronization
Documentation
//! Tests for built-in type implementations.

use crate::Automorph;
use automerge::{AutoCommit, ROOT};

#[test]
fn test_bool() {
    let mut doc = AutoCommit::new();

    true.save(&mut doc, &ROOT, "flag").unwrap();

    let mut value = false;
    value.update(&doc, &ROOT, "flag").unwrap();
    assert!(value);

    let restored = bool::load(&doc, &ROOT, "flag").unwrap();
    assert!(restored);
}

#[test]
fn test_integers() {
    let mut doc = AutoCommit::new();

    42i64.save(&mut doc, &ROOT, "num").unwrap();

    let mut value = 0i64;
    value.update(&doc, &ROOT, "num").unwrap();
    assert_eq!(value, 42);

    let restored = i64::load(&doc, &ROOT, "num").unwrap();
    assert_eq!(restored, 42);
}

#[test]
fn test_string() {
    let mut doc = AutoCommit::new();

    "hello"
        .to_string()
        .save(&mut doc, &ROOT, "greeting")
        .unwrap();

    let mut value = String::new();
    value.update(&doc, &ROOT, "greeting").unwrap();
    assert_eq!(value, "hello");

    let restored = String::load(&doc, &ROOT, "greeting").unwrap();
    assert_eq!(restored, "hello");
}

#[test]
fn test_option() {
    let mut doc = AutoCommit::new();

    let some_val: Option<i64> = Some(42);
    some_val.save(&mut doc, &ROOT, "maybe").unwrap();

    let restored = Option::<i64>::load(&doc, &ROOT, "maybe").unwrap();
    assert_eq!(restored, Some(42));

    let none_val: Option<i64> = None;
    none_val.save(&mut doc, &ROOT, "maybe").unwrap();

    let restored = Option::<i64>::load(&doc, &ROOT, "maybe").unwrap();
    assert_eq!(restored, None);
}

#[test]
fn test_vec() {
    let mut doc = AutoCommit::new();

    let values = vec![1i64, 2, 3, 4, 5];
    values.save(&mut doc, &ROOT, "numbers").unwrap();

    let restored = Vec::<i64>::load(&doc, &ROOT, "numbers").unwrap();
    assert_eq!(restored, vec![1, 2, 3, 4, 5]);
}

#[test]
fn test_tuple() {
    let mut doc = AutoCommit::new();

    let tuple = ("hello".to_string(), 42i64);
    tuple.save(&mut doc, &ROOT, "pair").unwrap();

    let restored = <(String, i64)>::load(&doc, &ROOT, "pair").unwrap();
    assert_eq!(restored, ("hello".to_string(), 42));
}

#[test]
fn test_hashmap() {
    use std::collections::HashMap;

    let mut doc = AutoCommit::new();

    let mut map = HashMap::new();
    map.insert("a".to_string(), 1i64);
    map.insert("b".to_string(), 2);

    map.save(&mut doc, &ROOT, "map").unwrap();

    let restored = HashMap::<String, i64>::load(&doc, &ROOT, "map").unwrap();
    assert_eq!(restored.get("a"), Some(&1));
    assert_eq!(restored.get("b"), Some(&2));
}

#[test]
fn test_version_aware() {
    let mut doc = AutoCommit::new();

    // Write initial value
    "version1"
        .to_string()
        .save(&mut doc, &ROOT, "data")
        .unwrap();
    let heads_v1 = doc.get_heads();

    // Write new value
    "version2"
        .to_string()
        .save(&mut doc, &ROOT, "data")
        .unwrap();

    // Read current value
    let current = String::load(&doc, &ROOT, "data").unwrap();
    assert_eq!(current, "version2");

    // Read historical value
    let historical = String::load_at(&doc, &ROOT, "data", &heads_v1).unwrap();
    assert_eq!(historical, "version1");
}

#[test]
fn test_nested_vec_with_empty_inner() {
    let mut doc = AutoCommit::new();

    // Vec containing an empty Vec - this is an edge case
    let value: Vec<Vec<i64>> = vec![vec![]];
    value.save(&mut doc, &ROOT, "nested").unwrap();

    let restored = Vec::<Vec<i64>>::load(&doc, &ROOT, "nested").unwrap();
    let expected: Vec<Vec<i64>> = vec![vec![]];
    assert_eq!(restored, expected);
}

#[test]
fn test_nested_vec_mixed() {
    let mut doc = AutoCommit::new();

    // Vec with mixed empty and non-empty inner vecs
    let value: Vec<Vec<i64>> = vec![vec![1, 2, 3], vec![], vec![4, 5]];
    value.save(&mut doc, &ROOT, "nested").unwrap();

    let restored = Vec::<Vec<i64>>::load(&doc, &ROOT, "nested").unwrap();
    assert_eq!(restored, value);
}