boko 0.5.0

Fast native ebook converter for EPUB, KFX, AZW3, and MOBI — the only KFX writer that needs no Kindle Previewer
Documentation
//! Regression test: KFX entities wrapped in a top-level Ion type annotation
//! (e.g. `$490::{ ... }`) must still have their fields populated when imported.
//!
//! Before the fix, `parse_entity_ion` returned the `Annotated` value as-is and
//! every downstream `.as_struct()` call returned `None`, silently dropping the
//! entity's fields. The fixture (`tests/fixtures/annotated_metadata.kfx.gz`) is
//! a 641-byte synthetic KFX container with a single `$490`-annotated
//! `book_metadata` entity. It is regenerated by
//! `cargo run --release --example build_annotated_kfx_fixture`.

use boko::Book;
use flate2::read::GzDecoder;
use std::io::Read;
use std::path::Path;

fn decompress_fixture() -> Option<tempfile::NamedTempFile> {
    let gz_path = "tests/fixtures/annotated_metadata.kfx.gz";
    if !Path::new(gz_path).exists() {
        eprintln!("Skipping test - fixture not found: {gz_path}");
        return None;
    }

    let gz_data = std::fs::read(gz_path).expect("Failed to read fixture");
    let mut decoder = GzDecoder::new(&gz_data[..]);
    let mut kfx_data = Vec::new();
    decoder
        .read_to_end(&mut kfx_data)
        .expect("Failed to decompress fixture");

    let mut tmp = tempfile::Builder::new()
        .suffix(".kfx")
        .tempfile()
        .expect("Failed to create temp file");
    std::io::Write::write_all(&mut tmp, &kfx_data).expect("Failed to write temp file");
    Some(tmp)
}

#[test]
fn annotated_book_metadata_entity_is_imported() {
    let Some(tmp) = decompress_fixture() else {
        return;
    };

    let book = Book::open(tmp.path()).expect("opening annotated-metadata KFX fixture");
    let meta = book.metadata();

    // Every field in the synthetic fixture's book_metadata entity must round-trip.
    // Without the annotation-stripping fix, all of these are empty / default.
    assert_eq!(meta.title, "Annotated Entity Test Book");
    assert_eq!(meta.authors, vec!["Boko Test Author".to_string()]);
    assert_eq!(meta.publisher.as_deref(), Some("Boko Test Press"));
    assert_eq!(meta.language, "en");
    assert_eq!(meta.identifier, "synthetic-book-id-0001");
    assert_eq!(meta.date.as_deref(), Some("2026-01-01"));
}