apsis-book/tests/docs_api.rs

112 lines
4.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Tests for the interface catalog reader.
//! 接口目录读取器的测试。
//!
//! They live here rather than inside the module so that `src/` holds no test
//! code, as it does in `apsis-rs`. An integration test is a separate crate and
//! reaches only what the library makes public, so the few internal items the
//! tests need are opened through `apsis_book::testkit`.
//!
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
//! 经 `apsis_book::testkit` 开放。
use apsis_book::docs::api::*;
use apsis_book::testkit::parse_item;
const SAMPLE: &str = r#"{
"generated_from": ["crates/orbit/apsis-sgp4/src/lib.rs"],
"crates": [
{
"name": "apsis-sgp4",
"layer": "orbit",
"summary": "The SGP4 and SDP4 analytical orbit propagator.",
"items": [
{"kind": "struct", "name": "Satellite", "signature": "pub struct Satellite { /* private */ }", "doc": "A prepared satellite.", "associated": false},
{"kind": "fn", "name": "propagate_minutes", "signature": "pub fn propagate_minutes(&self, minutes: f64) -> Result<State, PropagationError>", "doc": "Propagates by minutes.", "associated": true}
]
}
]
}"#;
#[test]
fn parses_the_catalog() {
let catalog = parse(SAMPLE);
assert_eq!(catalog.crates.len(), 1);
assert_eq!(catalog.item_count(), 2);
let krate = catalog.krate("apsis-sgp4").unwrap();
assert_eq!(krate.layer, "orbit");
assert_eq!(krate.items_of_kind("fn").len(), 1);
let (_, item) = catalog.find_item("propagate_minutes").unwrap();
assert!(item.is_function());
assert!(item.associated);
}
#[test]
fn malformed_input_yields_an_empty_catalog() {
assert!(parse("not json").is_empty());
assert!(parse("{}").is_empty());
}
#[test]
fn an_item_carries_both_languages() {
// `apsis-rs` writes the doc comment in English and then in Chinese, and
// the extractor separates the two into the catalogue.
// `apsis-rs` 把文档注释先写成英文、再写成中文,提取器把两者分开写入目录。
let item = r#"{"kind":"fn","name":"new","doc":"English.",
"doc_zh":"中文。","signature":"pub fn new()"}"#;
let parsed = parse_item(
&apsis_book::json::parse(item).expect("an item"),
"apsis-core",
None,
)
.expect("an item");
assert_eq!(parsed.doc.as_str(), "English.");
assert_eq!(parsed.doc_zh.as_deref(), Some("中文。"));
}
#[test]
fn an_item_without_a_translation_has_none() {
// A comment that is English only leaves the Chinese empty, and the
// reader is then shown the English rather than nothing.
// 只有英文的注释使中文一侧为空,此时读者看到的是英文,而不是什么都没有。
let item = r#"{"kind":"fn","name":"new","doc":"English.",
"signature":"pub fn new()"}"#;
let parsed = parse_item(
&apsis_book::json::parse(item).expect("an item"),
"apsis-core",
None,
)
.expect("an item");
assert_eq!(parsed.doc_zh, None);
}
#[test]
fn the_committed_catalogue_carries_both_languages_for_every_item() {
// The translation comes from the source doc comments rather than from a
// file maintained beside them, so a crate that was never translated shows
// up here rather than silently reading as English to a Chinese reader.
// 译文来自源码文档注释,而不是在它们旁边另行维护的文件,因此从未翻译过的
// crate 会在这里暴露出来,而不是悄悄以英文呈现给中文读者。
let catalog = apsis_book::docs::load_api_catalog();
let mut missing = Vec::new();
for krate in &catalog.crates {
if krate.summary_zh.is_none() {
missing.push(format!("{} (crate summary)", krate.name));
}
for item in &krate.items {
if item.doc_zh.is_none() {
missing.push(format!("{}::{}", krate.name, item.name));
}
}
}
assert!(
missing.is_empty(),
"{} entries have no Chinese: {:?}",
missing.len(),
&missing[..missing.len().min(8)]
);
}