logbook_test_baby 0.1.0

Record observations in a logbook file, or list previous observations.
Documentation
//! Records observations in a logbook file, or lists previous
//! observations.

use anyhow::{Ok, Result};
use std::{fs, io::Write, path::Path};

/// reads the contents of the logbook file at `path`.
/// 
/// Returns [`None`] if the file does not exist or is empty
/// 
/// # Errors
/// 
/// Returns any error from [`fs::exists`] or [`fs::read_to_string`]
pub fn read_logbook(path: impl AsRef<Path>) -> Result<Option<String>> {
    if fs::exists(&path)? {
        let text = fs::read_to_string(path)?;
        if text.is_empty() {
            Ok(None)
        } else {
            Ok(Some(text))
        }
    } else {
        Ok(None)
    }
}

/// Appends `msg` to the logbook file at `path`, creating the file
/// if necessary
/// 
/// # Errors
/// 
/// Returns any error from [`open`](fs::OpenOptions::open) or
/// [`writeln!`].
pub fn append_message(path: impl AsRef<Path>, msg: &str) -> Result<()> {
    let mut logbook = fs::File::options().create(true).append(true).open(path)?;
    writeln!(logbook, "{msg}")?;
    Ok(())
}

#[cfg(test)]
mod tests {

    use tempfile::tempdir;

    use super::*;

    #[test]
    fn test_read_logbook_fn_returns_none_if_file_does_not_exist() {
        let text = read_logbook("tests/data/bogus.txt").unwrap();
        assert_eq!(text, None, "Expected None, got {:?}", text);
    }

    #[test]
    fn test_read_logbook_fn_returns_none_for_empty_file() {
        let text = read_logbook("tests/data/empty.txt").unwrap();
        assert_eq!(text, None, "Expected None, got {:?}", text);
    }

    #[test]
    fn test_read_logbook_fn_reads_contents_of_a_file() {
        let text = read_logbook("tests/data/logbook.txt").unwrap().unwrap();
        assert_eq!(
            text.trim_end(),
            "hello world",
            "Expected hello world, got {}",
            text.trim_end()
        );
    }

    #[test]
    fn test_append_message_fn_creates_file_if_necessary() {
        let dir = tempdir().unwrap();
        let path = dir.path().join("newlog.txt");
        append_message(&path, "hello logbook").unwrap();
        let text = fs::read_to_string(path).unwrap();
        assert_eq!(
            text, "hello logbook\n",
            "Expected hello logbook, got {}",
            text
        );
    }

    #[test]
    fn test_append_message_fn_appends_msg_to_existing_file() {
        let dir = tempdir().unwrap();
        let path = dir.path().join("newlog.txt");
        fs::write(&path, "hello\n").unwrap();
        append_message(&path, "logbook").unwrap();
        let text = fs::read_to_string(path).unwrap();
        assert_eq!(
            text, "hello\nlogbook\n",
            "Expected hello\nlogbook\n, got {}",
            text
        );
    }
}