use rocksdb::{Options, DB}; use alle::todo::{self, add_due_date, change_due_date, remove_due_date}; use todo::{ add_todo, add_todo_note, add_todo_tag, complete_todo, delete_todo, edit_todo_note, get_all_todos, remove_todo_note, remove_todo_tag, uncomplete_todo, Status, Todo, }; #[test] fn test_add_todo_with_no_args() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note_arg: Option<&String> = None; let due_date_arg: Option<&String> = None; let result = add_todo(&db, &key, note_arg, due_date_arg); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); matches!(todo.status, Status::ToDo); assert_eq!(todo.name, key.to_string()); assert_eq!(todo.note, String::from("")); assert_eq!(0, todo.tags.len()) } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_with_note_and_due_date_args() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("whatever"); let note_arg: Option<&String> = Some(¬e); let due_date = String::from("17-07-2022"); let due_date_arg: Option<&String> = Some(&due_date); let result = add_todo(&db, &key, note_arg, due_date_arg); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); matches!(todo.status, Status::ToDo); assert_eq!(todo.name, key.to_string()); assert_eq!(todo.note, note); assert_eq!(todo.due_date, due_date); assert_eq!(0, todo.tags.len()) } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_already_exists() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let tags = Vec::new(); let due_date = String::from(""); insert_todo( &db, &key, Status::ToDo, &due_date, &String::from("no notes this time"), &tags, ); let note_arg: Option<&String> = None; let due_date_arg: Option<&String> = None; let result = add_todo(&db, &key, note_arg, due_date_arg); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name already exists"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_invalid_due_date() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note_arg: Option<&String> = None; let due_date = String::from("17-07-222022"); let due_date_arg: Option<&String> = Some(&due_date); let result = add_todo(&db, &key, note_arg, due_date_arg); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Invalid date format"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_list_all_todos_with_no_flags() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key1 = String::from("foo"); let note1 = String::from("random notes"); let due_date = String::from(""); let mut tags1: Vec = Vec::new(); tags1.push(String::from("another tag")); insert_todo(&db, &key1, Status::ToDo, &due_date, ¬e1, &tags1); let key2 = String::from("bar"); let note2 = String::from("random notes again"); let mut tags2: Vec = Vec::new(); tags2.push(String::from("random tag")); insert_todo(&db, &key2, Status::Done, &due_date, ¬e2, &tags2); // initialize status filter to be Option<&String> let status_filter: Option<&String> = None; let tag_filter: Option<&String> = None; let todos = get_all_todos(&db, status_filter, tag_filter); assert_eq!(2, todos.len()); let todo1 = todos.get(1).unwrap(); matches!(todo1.status, Status::Done); assert_eq!(todo1.name, key1.to_string()); assert_eq!(todo1.note, note1); assert_eq!(todo1.tags, tags1); let todo2 = todos.get(0).unwrap(); assert_eq!(todo2.name, key2.to_string()); matches!(todo2.status, Status::ToDo); assert_eq!(todo2.tags, tags2) } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_list_all_todos_with_flags() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key1 = String::from("foo"); let note1 = String::from("random notes"); let due_date = String::from(""); let mut tags1: Vec = Vec::new(); tags1.push(String::from("awesome")); insert_todo(&db, &key1, Status::ToDo, &due_date, ¬e1, &tags1); let key2 = String::from("bar"); let note2 = String::from("random notes again"); let mut tags2: Vec = Vec::new(); tags2.push(String::from("random tag")); insert_todo(&db, &key2, Status::Done, &due_date, ¬e2, &tags2); let todo_status = String::from("ToDo"); let status_filter: Option<&String> = Some(&todo_status); let awesome_tag = String::from("awesome"); let tag_filter: Option<&String> = Some(&awesome_tag); let todos = get_all_todos(&db, status_filter, tag_filter); assert_eq!(1, todos.len()); let todo1 = todos.get(0).unwrap(); matches!(todo1.status, Status::Done); assert_eq!(todo1.name, key1.to_string()); assert_eq!(todo1.note, note1); assert_eq!(todo1.tags, tags1); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_complete_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("whatever"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::ToDo, &due_date, ¬e, &tags); let result = complete_todo(&db, &key); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("whatever")); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_complete_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let result = complete_todo(&db, &key); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_uncomplete_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("whatever"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬e, &tags); let result = uncomplete_todo(&db, &key); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("whatever")); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_uncomplete_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let result = uncomplete_todo(&db, &key); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_note() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬e, &tags); let new_note = String::from("new note"); let result = add_todo_note(&db, &key, &new_note); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("new note")); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_note_with_existing_note() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("random note"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬e, &tags); let result = add_todo_note(&db, &key, ¬e); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "This todo already has a note"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_todo_note_with_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("random note"); let result = add_todo_note(&db, &key, ¬e); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_edit_todo_note() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("original note"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬e, &tags); let new_note = String::from("new note"); let result = edit_todo_note(&db, &key, &new_note); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("new note")); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_edit_todo_note_with_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let new_note = String::from("random note"); let result = edit_todo_note(&db, &key, &new_note); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_todo_note() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let note = String::from("original note"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬e, &tags); let result = remove_todo_note(&db, &key); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_todo_note_with_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let result = remove_todo_note(&db, &key); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_tag_to_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let tag = String::from("random tag"); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let result = add_todo_tag(&db, &key, &tag); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); assert_eq!(1, todo.tags.len()); assert_eq!(&tag, todo.tags.get(0).unwrap()) } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_tag_to_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let tag = String::from("random tag"); let result = add_todo_tag(&db, &key, &tag); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_tag_that_already_exists_to_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let mut tags = Vec::new(); let tag = String::from("randomt tag"); tags.push(tag.to_string()); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let result = add_todo_tag(&db, &key, &tag); assert_eq!(true, result.is_err()); assert_eq!( result.err().unwrap(), "This tag is has already been added to this todo" ); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_todo_tag() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let mut tags = Vec::new(); let tag = String::from("random tag"); tags.push(tag.to_string()); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let result = remove_todo_tag(&db, &key, &tag); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); assert_eq!(0, todo.tags.len()); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_todo_tag_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let tag = String::from("random tag"); let result = remove_todo_tag(&db, &key, &tag); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_missing_todo_tag() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let mut tags = Vec::new(); let tag = String::from("random tag"); tags.push(tag.to_string()); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let missing_tag = String::from("missing tag"); let result = remove_todo_tag(&db, &key, &missing_tag); assert_eq!(true, result.is_err()); assert_eq!( result.err().unwrap(), "This tag does not exist for this todo" ); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_due_date_for_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let new_due_date = String::from("17-07-2022"); let result = add_due_date(&db, &key, &new_due_date); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); assert_eq!(todo.due_date, new_due_date); assert_eq!(0, todo.tags.len()); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_invalid_due_date_for_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let new_due_date = String::from("17-07-202222"); let result = add_due_date(&db, &key, &new_due_date); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Invalid date format"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_add_due_date_for_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let due_date = String::from("17-07-2022"); let result = add_due_date(&db, &key, &due_date); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_change_due_date_for_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let new_due_date = String::from("17-07-2022"); let result = change_due_date(&db, &key, &new_due_date); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); assert_eq!(todo.due_date, new_due_date); assert_eq!(0, todo.tags.len()); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_change_invalid_due_date_for_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let new_due_date = String::from("17-07-202222"); let result = change_due_date(&db, &key, &new_due_date); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Invalid date format"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_change_due_date_for_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let due_date = String::from("17-07-2022"); let result = change_due_date(&db, &key, &due_date); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_due_date_for_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from(""); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::Done, &due_date, ¬es, &tags); let result = remove_due_date(&db, &key); assert_eq!(true, result.is_ok()); let db_value = String::from_utf8(db.get(&key).unwrap().unwrap()).unwrap(); let todo: Todo = serde_json::from_str(&db_value).unwrap(); assert_eq!(todo.name, key.to_string()); matches!(todo.status, Status::ToDo); assert_eq!(todo.note, String::from("")); assert_eq!(todo.due_date, String::from("")); assert_eq!(0, todo.tags.len()); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_remove_due_date_for_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let result = remove_due_date(&db, &key); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_delete_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let notes = String::from("whatever"); let tags = Vec::new(); let due_date = String::from(""); insert_todo(&db, &key, Status::ToDo, &due_date, ¬es, &tags); let result = delete_todo(&db, &key); assert_eq!(true, result.is_ok()); let db_value = db.get(key).unwrap(); assert_eq!(true, db_value.is_none()); } let _ = DB::destroy(&Options::default(), path); } #[test] fn test_delete_missing_todo() { let path = "/tmp"; { let db = DB::open_default(path).unwrap(); let key = String::from("foo"); let result = delete_todo(&db, &key); assert_eq!(true, result.is_err()); assert_eq!(result.err().unwrap(), "Todo with this name does not exist"); } let _ = DB::destroy(&Options::default(), path); } fn insert_todo( db: &DB, key: &String, status: Status, due_date: &String, notes: &String, tags: &Vec, ) { let todo = Todo { name: key.to_string(), status, due_date: due_date.to_string(), note: notes.to_string(), tags: tags.to_vec(), }; let serialized = serde_json::to_string(&todo).unwrap(); db.put(&key, serialized).unwrap(); } #[test] #[ignore] fn destroy_db() { let path = "/tmp"; let _ = DB::destroy(&Options::default(), path); }