|
4 | 4 |
|
5 | 5 | use std::fs; |
6 | 6 |
|
7 | | -use crate::screens::build_screens; |
| 7 | +use crate::screens::{build_screens, refine_screen_structures}; |
8 | 8 | use crate::types::{SessionOcrBlock, TextBox}; |
9 | 9 |
|
10 | 10 | /// 测试辅助:构造会话 OCR 块(region=full,可带 bbox/screen_id/region_kind)。 |
@@ -145,6 +145,70 @@ fn build_screens_empty_and_no_full_blocks() { |
145 | 145 | assert!(build_screens(&subtitle_only, Some(&dir)).is_empty()); |
146 | 146 | } |
147 | 147 |
|
| 148 | +#[test] |
| 149 | +fn refine_structures_from_artifact() { |
| 150 | + // Arrange:屏内 table/formula 结构块 + 课后精修产物(frame_ms 在屏区间内) |
| 151 | + use crate::artifact::{ArtifactBlock, ArtifactKind, BlockPayload, BlockRefs, BlockSource, SessionArtifact}; |
| 152 | + use crate::table_reconstruct::TableBlock; |
| 153 | + let dir = tmp_images_dir("refine", &[]); |
| 154 | + let blocks = vec![ |
| 155 | + blk(1, 2_000, "表格标题", Some(1), Some((100.0, 100.0, 300.0, 40.0)), None), |
| 156 | + blk(2, 2_000, "| A | B |", Some(1), Some((100.0, 200.0, 300.0, 60.0)), Some("table")), |
| 157 | + blk(3, 2_000, "x^2+1", Some(1), Some((100.0, 300.0, 200.0, 40.0)), Some("formula")), |
| 158 | + ]; |
| 159 | + let mut screens = build_screens(&blocks, Some(&dir)); |
| 160 | + let artifact = SessionArtifact { |
| 161 | + session_id: 1, |
| 162 | + profile: String::new(), |
| 163 | + blocks: vec![ |
| 164 | + ArtifactBlock { |
| 165 | + id: 1, |
| 166 | + kind: ArtifactKind::Table, |
| 167 | + refs: BlockRefs { segment_id: None, ocr_block_id: None, frame_ms: Some(2_000) }, |
| 168 | + payload: BlockPayload::Table(TableBlock { |
| 169 | + markdown: "| A | B |\n|---|---|\n| 1 | 2 |".to_string(), |
| 170 | + structure_confidence: 0.9, |
| 171 | + cell_refs: Vec::new(), |
| 172 | + }), |
| 173 | + order: 0, |
| 174 | + source: BlockSource::Local, |
| 175 | + }, |
| 176 | + ArtifactBlock { |
| 177 | + id: 2, |
| 178 | + kind: ArtifactKind::Formula, |
| 179 | + refs: BlockRefs { segment_id: None, ocr_block_id: None, frame_ms: Some(2_000) }, |
| 180 | + payload: BlockPayload::Formula(crate::formula_reconstruct::FormulaBlock { |
| 181 | + latex: "x^2+1".to_string(), |
| 182 | + source_text: "x2+1".to_string(), |
| 183 | + confidence: 0.8, |
| 184 | + }), |
| 185 | + order: 1, |
| 186 | + source: BlockSource::Local, |
| 187 | + }, |
| 188 | + ], |
| 189 | + }; |
| 190 | + // Act |
| 191 | + refine_screen_structures(&mut screens, Some(&artifact)); |
| 192 | + // Assert:表格/公式 rendered 填充 |
| 193 | + let s = &screens[0]; |
| 194 | + let table = s.structure.iter().find(|st| st.kind == "table").unwrap(); |
| 195 | + assert_eq!(table.rendered.as_deref(), Some("| A | B |\n|---|---|\n| 1 | 2 |")); |
| 196 | + let formula = s.structure.iter().find(|st| st.kind == "formula").unwrap(); |
| 197 | + assert_eq!(formula.rendered.as_deref(), Some("$$x^2+1$$")); |
| 198 | +} |
| 199 | + |
| 200 | +#[test] |
| 201 | +fn refine_structures_none_without_artifact() { |
| 202 | + // Arrange:无产物 + 屏结构块 |
| 203 | + let dir = tmp_images_dir("refine-none", &[]); |
| 204 | + let blocks = vec![blk(1, 2_000, "| A |", Some(1), Some((100.0, 200.0, 300.0, 60.0)), Some("table"))]; |
| 205 | + let mut screens = build_screens(&blocks, Some(&dir)); |
| 206 | + // Act:None 产物 → 无操作(rendered 保持 None) |
| 207 | + refine_screen_structures(&mut screens, None); |
| 208 | + // Assert |
| 209 | + assert_eq!(screens[0].structure[0].rendered, None); |
| 210 | +} |
| 211 | + |
148 | 212 | #[test] |
149 | 213 | fn image_ref_matches_nearest_at_or_before_first_seen() { |
150 | 214 | // Arrange:归档图 2000/10000/30000;屏 first_seen=36404 → 最近 ≤ 为 30000 |
|
0 commit comments