use super::*;
#[test]
fn test_generate_docs_empty_api() {
let api = ApiSurface {
crate_name: "test".to_string(),
version: "0.1.0".to_string(),
types: vec![],
functions: vec![],
enums: vec![],
errors: vec![],
excluded_type_paths: ::std::collections::HashMap::new(),
excluded_trait_names: ::std::collections::HashSet::new(),
services: vec![],
handler_contracts: vec![],
unsupported_public_items: Vec::new(),
};
let config = make_test_config();
let files = generate_docs(&api, &config, &[Language::Python], "docs").unwrap();
assert_eq!(files.len(), 4);
let lang_file = files
.iter()
.find(|f| f.path.to_str().unwrap().contains("api-python"))
.unwrap();
assert!(lang_file.content.contains("Python API Reference"));
assert!(lang_file.content.contains("v0.1.0"));
}
#[test]
fn test_generate_docs_respects_language_excludes() {
let config = config_from_toml(
r#"
[workspace]
languages = ["python", "go"]
[[crates]]
name = "mylib"
sources = ["src/lib.rs"]
[crates.python]
exclude_functions = ["interact"]
exclude_types = ["InteractionResult"]
[crates.ffi]
exclude_functions = ["ffi_only"]
exclude_types = ["FfiHidden"]
"#,
);
let mut api = make_minimal_api("1.2.3");
api.functions = vec![
make_function("interact", vec![], TypeRef::Unit, false, None),
make_function("scrape", vec![], TypeRef::Unit, false, None),
make_function("ffi_only", vec![], TypeRef::Unit, false, None),
];
api.types = vec![empty_type("InteractionResult"), empty_type("FfiHidden")];
let files = generate_docs(&api, &config, &[Language::Python, Language::Go], "out").unwrap();
let python = files
.iter()
.find(|f| f.path.to_str().unwrap().contains("api-python"))
.unwrap();
let go = files
.iter()
.find(|f| f.path.to_str().unwrap().contains("api-go"))
.unwrap();
assert!(!python.content.contains("interact()"));
assert!(python.content.contains("scrape()"));
assert!(!python.content.contains("InteractionResult"));
assert!(!go.content.contains("ffi_only()"));
assert!(!go.content.contains("FfiHidden"));
assert!(go.content.contains("Interact()"));
}
#[test]
fn test_generate_docs_produces_one_file_per_language_plus_three_shared() {
let api = make_minimal_api("1.2.3");
let config = make_test_config();
let files = generate_docs(&api, &config, &[Language::Python, Language::Node], "out").unwrap();
assert_eq!(files.len(), 5);
let paths: Vec<&str> = files.iter().map(|f| f.path.to_str().unwrap()).collect();
assert!(paths.iter().any(|p| p.contains("api-python")));
assert!(paths.iter().any(|p| p.contains("api-typescript")));
assert!(paths.iter().any(|p| p.contains("configuration")));
assert!(paths.iter().any(|p| p.contains("types")));
assert!(paths.iter().any(|p| p.contains("errors")));
}
#[test]
fn test_generate_docs_all_output_files_end_with_newline() {
let api = make_minimal_api("0.1.0");
let config = make_test_config();
let files = generate_docs(&api, &config, &[Language::Python], "out").unwrap();
for file in &files {
assert!(
file.content.ends_with('\n'),
"file {:?} must end with trailing newline",
file.path
);
}
}
#[test]
fn test_generate_docs_output_dir_prefix_in_all_paths() {
let api = make_minimal_api("0.1.0");
let config = make_test_config();
let files = generate_docs(&api, &config, &[Language::Python], "custom/output/dir").unwrap();
for file in &files {
assert!(
file.path.to_str().unwrap().starts_with("custom/output/dir"),
"all paths must be under output_dir: {:?}",
file.path
);
}
}
#[test]
fn test_generate_docs_multiple_languages_produce_correct_slugs() {
let api = make_minimal_api("0.1.0");
let config = make_test_config();
let langs = [
Language::Python,
Language::Node,
Language::Go,
Language::Java,
Language::Ruby,
];
let expected_slugs = ["api-python", "api-typescript", "api-go", "api-java", "api-ruby"];
let files = generate_docs(&api, &config, &langs, "docs/api").unwrap();
assert_eq!(files.len(), 8);
for slug in &expected_slugs {
assert!(
files.iter().any(|f| f.path.to_str().unwrap().contains(slug)),
"expected file with slug {slug}"
);
}
}