//! Comprehensive tests for DocBook extractor supporting both 4.x and 5.x versions. #![cfg(feature = "xml")] use kreuzberg::core::config::ExtractionConfig; use kreuzberg::extraction::derive::derive_extraction_result; use kreuzberg::plugins::{DocumentExtractor, Plugin}; use kreuzberg::types::ExtractionResult; use std::path::PathBuf; /// Helper to get absolute path to test documents fn test_file_path(filename: &str) -> PathBuf { let manifest_dir = env!("CARGO_MANIFEST_DIR"); PathBuf::from(manifest_dir) .parent() .expect("Operation failed") .parent() .expect("Operation failed") .join("test_documents") .join("docbook") .join(filename) } /// DocBook 4.x extractor test helper async fn extract_docbook4_file(filename: &str) -> kreuzberg::Result { let extractor = kreuzberg::extractors::DocbookExtractor; let path = test_file_path(filename); let config = ExtractionConfig::default(); let doc = extractor .extract_file(&path, "application/docbook+xml", &config) .await?; Ok(derive_extraction_result(doc, true, kreuzberg::OutputFormat::Plain)) } /// DocBook 5.x extractor test helper async fn extract_docbook5_file(filename: &str) -> kreuzberg::Result { let extractor = kreuzberg::extractors::DocbookExtractor; let path = test_file_path(filename); let config = ExtractionConfig::default(); let doc = extractor .extract_file(&path, "application/docbook+xml", &config) .await?; Ok(derive_extraction_result(doc, true, kreuzberg::OutputFormat::Plain)) } /// Helper to extract bytes directly async fn extract_docbook_bytes(content: &[u8], mime_type: &str) -> kreuzberg::Result { let extractor = kreuzberg::extractors::DocbookExtractor; let config = ExtractionConfig::default(); let doc = extractor.extract_bytes(content, mime_type, &config).await?; Ok(derive_extraction_result(doc, true, kreuzberg::OutputFormat::Plain)) } #[test] fn test_docbook_extractor_plugin_interface() { let extractor = kreuzberg::extractors::DocbookExtractor; assert_eq!(extractor.name(), "docbook-extractor"); assert!(extractor.initialize().is_ok()); assert!(extractor.shutdown().is_ok()); } #[test] fn test_docbook_extractor_supported_mime_types() { let extractor = kreuzberg::extractors::DocbookExtractor; let mime_types = extractor.supported_mime_types(); assert!(mime_types.contains(&"application/docbook+xml")); assert!(mime_types.contains(&"text/docbook")); } #[test] fn test_docbook_extractor_priority() { let extractor = kreuzberg::extractors::DocbookExtractor; assert_eq!(extractor.priority(), 50); } #[tokio::test] async fn test_docbook4_chapter_extraction() { let result = extract_docbook4_file("docbook-chapter.docbook").await; assert!(result.is_ok(), "Failed to extract DocBook 4 chapter"); let result = result.expect("Operation failed"); assert!(!result.content.is_empty(), "Content should not be empty"); assert!( result.content.contains("Test Chapter"), "Content should contain chapter title" ); assert!( result.content.contains("Like a Sect1"), "Content should contain section titles" ); } #[tokio::test] async fn test_docbook5_reader_extraction() { let result = extract_docbook5_file("docbook-reader.docbook").await; assert!(result.is_ok(), "Failed to extract DocBook 5 file"); let result = result.expect("Operation failed"); assert!(!result.content.is_empty(), "Content should not be empty"); assert!( result.content.contains("Pandoc Test Suite"), "Content should contain article title" ); } #[tokio::test] async fn test_docbook_xref_extraction() { let result = extract_docbook4_file("docbook-xref.docbook").await; assert!(result.is_ok(), "Failed to extract DocBook with xref elements"); let result = result.expect("Operation failed"); assert!(!result.content.is_empty(), "Content should not be empty"); assert!( result.content.contains("An Example Book"), "Content should contain book title" ); assert!( result.content.contains("XRef Samples"), "Content should contain xref chapter" ); } #[tokio::test] async fn test_docbook_tables_extraction() { let result = extract_docbook4_file("tables.docbook4").await; assert!(result.is_ok(), "Failed to extract DocBook with tables"); let result = result.expect("Operation failed"); assert!(!result.content.is_empty(), "Content should not be empty"); assert!(!result.tables.is_empty(), "Should extract tables from DocBook"); } #[tokio::test] async fn test_docbook5_tables_extraction() { let result = extract_docbook5_file("tables.docbook5").await; assert!(result.is_ok(), "Failed to extract DocBook 5 with tables"); let result = result.expect("Operation failed"); assert!(!result.content.is_empty(), "Content should not be empty"); assert!(!result.tables.is_empty(), "Should extract tables from DocBook 5"); } #[tokio::test] async fn test_docbook_metadata_extraction() { let result = extract_docbook5_file("docbook-reader.docbook").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(!result.content.is_empty()); } #[tokio::test] async fn test_docbook_section_hierarchy() { let result = extract_docbook4_file("docbook-chapter.docbook").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); let content = &result.content; assert!(content.contains("Like a Sect1")); assert!(content.contains("Like a Sect2")); assert!(content.contains("Like a Sect3")); assert!(content.contains("Like a Sect4")); } #[tokio::test] async fn test_docbook_paragraph_extraction() { let result = extract_docbook4_file("docbook-chapter.docbook").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!( result.content.contains("This chapter uses recursive sections"), "Should extract paragraph content" ); } #[tokio::test] async fn test_docbook_paragraph_content() { let docbook = r#"
Test Article This is a test paragraph. This is another paragraph with emphasized text.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Test Article")); assert!(result.content.contains("This is a test paragraph")); assert!(result.content.contains("another paragraph")); } #[tokio::test] async fn test_docbook_code_block_extraction() { let docbook = r#"
Here is code: def hello(): print("world")
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("def hello")); assert!(result.content.contains("print")); } #[tokio::test] async fn test_docbook_mixed_content() { let docbook = r#" Test Book Chapter 1
Section 1.1 Paragraph in section.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Test Book")); assert!(result.content.contains("Chapter 1")); assert!(result.content.contains("Section 1.1")); assert!(result.content.contains("Paragraph in section")); } #[tokio::test] async fn test_docbook_namespaced_5x_parsing() { let docbook5 = r#"
DocBook 5 Article John Doe 2024-01-01
Introduction Welcome to DocBook 5.
"#; let result = extract_docbook_bytes(docbook5.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("DocBook 5 Article")); assert!(result.content.contains("Welcome to DocBook 5")); } #[tokio::test] async fn test_docbook_link_handling() { let docbook = r#"
Links Test See example site.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("example")); } #[tokio::test] async fn test_docbook_mime_type_detection() { let docbook = r#"
Test
"#; let result1 = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result1.is_ok()); let result2 = extract_docbook_bytes(docbook.as_bytes(), "text/docbook").await; assert!(result2.is_ok()); } #[tokio::test] async fn test_docbook_empty_sections() { let docbook = r#"
Empty Sections
Empty Section
Section with Content Content here
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Empty Section")); assert!(result.content.contains("Section with Content")); assert!(result.content.contains("Content here")); } #[tokio::test] async fn test_docbook_itemized_list() { let docbook = r#"
List Test First item Second item Third item
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("First item")); assert!(result.content.contains("Second item")); assert!(result.content.contains("Third item")); } #[tokio::test] async fn test_docbook_ordered_list() { let docbook = r#"
Ordered List Test First step Second step Third step
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("First step")); assert!(result.content.contains("Second step")); assert!(result.content.contains("Third step")); } #[tokio::test] async fn test_docbook_blockquote() { let docbook = r#"
Blockquote Test
This is a quoted passage.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("quoted passage")); } #[tokio::test] async fn test_docbook_figure() { let docbook = r#"
Figure Test
Sample Figure This is a figure description.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Figure")); } #[tokio::test] async fn test_docbook_footnote() { let docbook = r#"
Footnote Test Here is some text with a footnoteThis is the footnote content.
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("text with a footnote")); assert!(result.content.contains("footnote content")); } #[tokio::test] async fn test_docbook_mixed_content_with_lists() { let docbook = r#"
Mixed Content Introduction paragraph. List item 1 List item 2 Conclusion paragraph. code example
"#; let result = extract_docbook_bytes(docbook.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Introduction paragraph")); assert!(result.content.contains("List item 1")); assert!(result.content.contains("List item 2")); assert!(result.content.contains("Conclusion paragraph")); assert!(result.content.contains("code example")); } #[tokio::test] async fn test_docbook_namespaced_lists() { let docbook5 = r#"
Lists in DocBook 5 Namespaced item 1 Namespaced item 2
"#; let result = extract_docbook_bytes(docbook5.as_bytes(), "application/docbook+xml").await; assert!(result.is_ok()); let result = result.expect("Operation failed"); assert!(result.content.contains("Namespaced item 1")); assert!(result.content.contains("Namespaced item 2")); }