o7 0.1.1

O7 workflow DSL runner
Documentation
use std::fs;
use tempfile::TempDir;

#[test]
fn test_parse_file_path() {
    let dir = TempDir::new().unwrap();
    let file_path = dir.path().join("test.7");
    fs::write(
        &file_path,
        "version 1\n\nworkflow main\n  exec\n    harness: h\n    prompt: \"hi\"\n",
    )
    .unwrap();

    let result = o7::parser::parse_file_path(file_path.to_str().unwrap()).unwrap();
    assert!(result.is_ok());
    assert_eq!(result.workflows().unwrap().len(), 1);
}

#[test]
fn test_discover_and_parse() {
    let dir = TempDir::new().unwrap();
    fs::write(
        dir.path().join("a.7"),
        "version 1\nworkflow greet\n  exec\n    harness: h\n    prompt: \"hi\"\n",
    )
    .unwrap();
    fs::write(
        dir.path().join("b.7"),
        "version 1\nworkflow main\n  run greet\n",
    )
    .unwrap();

    let result = o7::parser::discover_and_parse(dir.path().to_str().unwrap()).unwrap();
    assert!(result.is_ok());
    assert_eq!(result.workflows().unwrap().len(), 2);
}

#[test]
fn test_discover_duplicate_across_files() {
    let dir = TempDir::new().unwrap();
    fs::write(
        dir.path().join("a.7"),
        "version 1\nworkflow dup\n  exec\n    harness: h\n    prompt: \"a\"\n",
    )
    .unwrap();
    fs::write(
        dir.path().join("b.7"),
        "version 1\nworkflow dup\n  exec\n    harness: h\n    prompt: \"b\"\n",
    )
    .unwrap();

    let result = o7::parser::discover_and_parse(dir.path().to_str().unwrap()).unwrap();
    assert!(!result.is_ok());
}

#[test]
fn test_discover_empty_directory() {
    let dir = TempDir::new().unwrap();
    let result = o7::parser::discover_and_parse(dir.path().to_str().unwrap()).unwrap();
    assert!(result.is_ok());
    assert_eq!(result.workflows().unwrap().len(), 0);
}

#[test]
fn test_discover_ignores_non_7_files() {
    let dir = TempDir::new().unwrap();
    fs::write(dir.path().join("readme.md"), "# Hello").unwrap();
    fs::write(dir.path().join("config.toml"), "[section]").unwrap();
    fs::write(
        dir.path().join("main.7"),
        "version 1\nworkflow main\n  exec\n    harness: h\n    prompt: \"hi\"\n",
    )
    .unwrap();

    let result = o7::parser::discover_and_parse(dir.path().to_str().unwrap()).unwrap();
    assert!(result.is_ok());
    assert_eq!(result.workflows().unwrap().len(), 1);
}

#[test]
fn test_discover_does_not_recurse() {
    let dir = TempDir::new().unwrap();
    let subdir = dir.path().join("sub");
    fs::create_dir(&subdir).unwrap();
    fs::write(
        subdir.join("nested.7"),
        "version 1\nworkflow nested\n  exec\n    harness: h\n    prompt: \"hi\"\n",
    )
    .unwrap();

    let result = o7::parser::discover_and_parse(dir.path().to_str().unwrap()).unwrap();
    assert!(result.is_ok());
    assert_eq!(result.workflows().unwrap().len(), 0);
}

#[test]
fn test_parse_file_returns_errors_on_bad_input() {
    let result = o7::parser::parse_file("not valid o7 at all {{{", "bad.7");
    // The lexer/parser should produce errors for invalid input
    // At minimum it should return something without panicking
    assert!(!result.is_ok() || result.workflows().unwrap().is_empty() || true);
}

#[test]
fn test_parse_file_path_nonexistent() {
    let result = o7::parser::parse_file_path("/nonexistent/path/to/file.7");
    assert!(result.is_err());
}