Skip to main content

text_document_test_harness/
lib.rs

1//! Shared test setup utilities for text-document crate tests.
2//!
3//! Provides helpers to create an in-memory document with content,
4//! export text, and traverse the entity tree — eliminating the need
5//! for each feature crate to depend on `direct_access` and `document_io`
6//! in its dev-dependencies.
7
8use anyhow::Result;
9use common::database::db_context::DbContext;
10use common::event::EventHub;
11use common::types::EntityId;
12use common::undo_redo::UndoRedoManager;
13use std::sync::Arc;
14
15// Re-export commonly used types and controllers for convenience
16pub use common::direct_access::block::block_repository::BlockRelationshipField;
17pub use common::direct_access::document::document_repository::DocumentRelationshipField;
18pub use common::direct_access::frame::frame_repository::FrameRelationshipField;
19pub use common::direct_access::root::root_repository::RootRelationshipField;
20
21pub use direct_access::block::block_controller;
22pub use direct_access::document::document_controller;
23pub use direct_access::document::dtos::CreateDocumentDto;
24pub use direct_access::frame::frame_controller;
25pub use direct_access::inline_element::inline_element_controller;
26pub use direct_access::root::dtos::CreateRootDto;
27pub use direct_access::root::root_controller;
28
29pub use document_io::document_io_controller;
30pub use document_io::ImportPlainTextDto;
31
32/// Create an in-memory database with a Root and empty Document.
33///
34/// Returns `(DbContext, Arc<EventHub>, UndoRedoManager)`.
35pub fn setup() -> Result<(DbContext, Arc<EventHub>, UndoRedoManager)> {
36    let db_context = DbContext::new()?;
37    let event_hub = Arc::new(EventHub::new());
38    let mut undo_redo_manager = UndoRedoManager::new();
39
40    let root =
41        root_controller::create_orphan(&db_context, &event_hub, &CreateRootDto::default())?;
42
43    let _doc = document_controller::create(
44        &db_context,
45        &event_hub,
46        &mut undo_redo_manager,
47        None,
48        &CreateDocumentDto::default(),
49        root.id,
50        -1,
51    )?;
52
53    Ok((db_context, event_hub, undo_redo_manager))
54}
55
56/// Create an in-memory database with a Root, Document, and imported text content.
57///
58/// Returns `(DbContext, Arc<EventHub>, UndoRedoManager)`.
59pub fn setup_with_text(text: &str) -> Result<(DbContext, Arc<EventHub>, UndoRedoManager)> {
60    let (db_context, event_hub, undo_redo_manager) = setup()?;
61
62    document_io_controller::import_plain_text(
63        &db_context,
64        &event_hub,
65        &ImportPlainTextDto {
66            plain_text: text.to_string(),
67        },
68    )?;
69
70    Ok((db_context, event_hub, undo_redo_manager))
71}
72
73/// Export the current document as plain text.
74pub fn export_text(db_context: &DbContext, event_hub: &Arc<EventHub>) -> Result<String> {
75    let dto = document_io_controller::export_plain_text(db_context, event_hub)?;
76    Ok(dto.plain_text)
77}
78
79/// Get the first frame's block IDs (sorted by document_position).
80pub fn get_block_ids(db_context: &DbContext) -> Result<Vec<EntityId>> {
81    let root_rels =
82        root_controller::get_relationship(db_context, &1, &RootRelationshipField::Document)?;
83    let doc_id = root_rels[0];
84    let frame_ids = document_controller::get_relationship(
85        db_context,
86        &doc_id,
87        &DocumentRelationshipField::Frames,
88    )?;
89    let frame_id = frame_ids[0];
90    let block_ids = frame_controller::get_relationship(
91        db_context,
92        &frame_id,
93        &FrameRelationshipField::Blocks,
94    )?;
95    Ok(block_ids)
96}
97
98/// Get the element IDs for a given block.
99pub fn get_element_ids(db_context: &DbContext, block_id: &EntityId) -> Result<Vec<EntityId>> {
100    block_controller::get_relationship(db_context, block_id, &BlockRelationshipField::Elements)
101}
102
103/// Get the first block's element IDs.
104pub fn get_first_block_element_ids(db_context: &DbContext) -> Result<Vec<EntityId>> {
105    let block_ids = get_block_ids(db_context)?;
106    get_element_ids(db_context, &block_ids[0])
107}
108
109/// Get the first frame ID for the document.
110pub fn get_frame_id(db_context: &DbContext) -> Result<EntityId> {
111    let root_rels =
112        root_controller::get_relationship(db_context, &1, &RootRelationshipField::Document)?;
113    let doc_id = root_rels[0];
114    let frame_ids = document_controller::get_relationship(
115        db_context,
116        &doc_id,
117        &DocumentRelationshipField::Frames,
118    )?;
119    Ok(frame_ids[0])
120}
121
122/// Basic document statistics retrieved directly from entity data.
123pub struct BasicStats {
124    pub character_count: i64,
125    pub block_count: i64,
126    pub frame_count: i64,
127}
128
129/// Get basic document statistics by reading the Document entity directly
130/// — avoids depending on the document_inspection crate.
131pub fn get_document_stats(db_context: &DbContext) -> Result<BasicStats> {
132    let root_rels =
133        root_controller::get_relationship(db_context, &1, &RootRelationshipField::Document)?;
134    let doc_id = root_rels[0];
135    let doc = document_controller::get(db_context, &doc_id)?
136        .ok_or_else(|| anyhow::anyhow!("Document not found"))?;
137    let frame_ids = document_controller::get_relationship(
138        db_context,
139        &doc_id,
140        &DocumentRelationshipField::Frames,
141    )?;
142    Ok(BasicStats {
143        character_count: doc.character_count,
144        block_count: doc.block_count,
145        frame_count: frame_ids.len() as i64,
146    })
147}