dodo 0.3.1

Basic persistence library designed to be a quick and easy way to create a persistent storage.
Documentation
use uuid::Uuid;

use dodo::{Memory, prelude::*};

use crate::common::Person;

#[test]
fn can_create_collection() {
    fixture::Collection::new(Memory::new());
}

#[test]
fn can_find_by_id() {
    let mut collection = fixture::Collection::new(Memory::new());
    let (id, expected_entity) = fixture::create_entity_in(&mut collection);

    let actual_entity = collection.find(id).expect("entity should exists");

    assert_eq!(expected_entity, actual_entity, "entities should be the same.");
}

#[test]
fn cant_find_absent_entity() {
    let collection = fixture::Collection::new(Memory::new());
    let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();

    let entity = collection.find(id);

    assert!(entity.expect_err("entity should not exist").is_not_found(), "entity should not exist");
}

#[test]
fn can_find_all_entities() {
    let mut collection = fixture::Collection::new(Memory::new());
    let (_, entity1) = fixture::create_entity_in(&mut collection);
    let (_, entity2) = fixture::create_entity_in(&mut collection);

    let entities = collection
        .find_all().expect("could not read collection")
        .collect().expect("could not read collection");

    assert!(entities.contains(&entity1), "entity 1 should exist");
    assert!(entities.contains(&entity2), "entity 2 should exist");
}

#[test]
fn can_shuffle_entities() {
    let mut collection = fixture::Collection::new(Memory::new());
    let (_, entity1) = fixture::create_entity_in(&mut collection);
    let (_, entity2) = fixture::create_entity_in(&mut collection);

    let entities = collection
        .find_all().expect("could not read collection")
        .shuffled()
        .collect().expect("could not read collection");

    //As long as all entities are yielded, this is considered a success.
    assert!(entities.contains(&entity1), "entity 1 should exist");
    assert!(entities.contains(&entity2), "entity 2 should exist");
}

#[test]
fn can_insert_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::new();

    collection.insert(&mut entity).expect("could not insert in collection");

    fixture::assert_entity_equals(&collection, &entity);
}

#[test]
fn should_assign_new_id_when_inserted() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::new();
    collection.insert(&mut entity).expect("could not insert in collection");
    let old_id = entity.id.expect("entity should have an id");

    collection.insert(&mut entity).expect("could not insert in collection");
    let new_id = entity.id.expect("entity should have a new id");

    assert_ne!(old_id, new_id, "entity should have a new id");
}

#[test]
fn can_update_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::with_age(42);
    collection.insert(&mut entity).expect("could not insert in collection");

    entity.age = 18;
    collection.update(&mut entity).expect("could not update collection");

    fixture::assert_entity_equals(&collection, &entity);
}

#[test]
fn cant_update_absent_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::with_age(42);

    let result = collection.update(&mut entity);

    assert!(result.is_err(), "entity should not have been updated");
}

#[test]
fn can_upsert_existing_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::with_age(42);
    collection.insert(&mut entity).expect("could not insert in collection");

    entity.age = 18;
    collection.upsert(&mut entity).expect("could not upsert in collection");

    fixture::assert_entity_equals(&collection, &entity);
}

#[test]
fn cant_upsert_absent_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();
    let mut entity = Person::with_id(id);
    collection.insert(&mut entity).expect("could not insert in collection");

    entity.age = 18;
    collection.upsert(&mut entity).expect("could not upsert in collection");

    fixture::assert_entity_equals(&collection, &entity);
}

#[test]
fn should_keep_id_when_upserted() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::new();
    collection.insert(&mut entity).expect("could not insert in collection");

    entity.age = 18;
    //Clone entity to leave the current one untouched.
    collection.upsert(&mut entity.clone()).expect("could not upsert in collection");

    fixture::assert_entity_equals(&collection, &entity);
}

#[test]
fn can_delete_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let mut entity = Person::new();
    collection.insert(&mut entity).expect("could not insert in collection");
    let id = entity.id.expect("entity should have an id");

    let deleted = collection.delete(id).expect("could not delete from collection");

    assert!(deleted, "something should have been deleted");
    fixture::assert_entity_not_exists(&collection, id);
}

#[test]
fn can_delete_absent_entity() {
    let mut collection = fixture::Collection::new(Memory::new());
    let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap();

    let deleted = collection.delete(id).expect("could not delete from collection");

    assert!(!deleted, "entity should not have been deleted");
    fixture::assert_entity_not_exists(&collection, id);
}

#[test]
fn can_clear_collection() {
    let mut collection = fixture::Collection::new(Memory::new());
    let (id1, _) = fixture::create_entity_in(&mut collection);
    let (id2, _) = fixture::create_entity_in(&mut collection);

    collection.clear().expect("collection should have been clearable");

    fixture::assert_entity_not_exists(&collection, id1);
    fixture::assert_entity_not_exists(&collection, id2);
}

#[test]
fn can_clear_empty_collection() {
    let mut collection = fixture::Collection::new(Memory::new());

    collection.clear().expect("collection should have been clearable");
}

mod fixture {
    use uuid::Uuid;

    use dodo::{Memory, prelude::*};

    use crate::common::Person;

    pub type Collection = dodo::Collection<Person, Memory, JsonSerializer>;

    pub fn create_entity_in(collection: &mut Collection) -> (Uuid, Person) {
        let mut entity = Person::new();
        collection.insert(&mut entity).expect("could not insert in collection");
        let id = entity.id.expect("unable to get id from entity");
        (id, entity)
    }

    pub fn assert_entity_equals(collection: &Collection, expected_entity: &Person) {
        let actual_entity = collection.find(expected_entity.id.expect("unable to get id from entity")).expect("entity should exist");
        assert_eq!(*expected_entity, actual_entity, "entities should be the same.");
    }

    pub fn assert_entity_not_exists(collection: &Collection, id: Uuid) {
        assert!(collection.find(id).expect_err("entity should not exist").is_not_found(), "entity should not exist");
    }
}