test: add extract_epub_chapter_texts + strip_html unit tests (DOC-FULL-024)
- 7 strip_html tests: remove tags, collapse whitespace, nested tags, self-closing tags, attributes, empty input, plain text - 4 extract_epub_chapter_texts tests: chapters with HTML, empty chapter filtered, all empty, plain text preserved - epub_with_chapter_text helper builds EPUB with custom chapter content Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
7570717ec8
commit
7d82a5676c
@ -655,4 +655,141 @@ mod tests {
|
|||||||
assert_eq!(chapters[1].title, "Chapter 2");
|
assert_eq!(chapters[1].title, "Chapter 2");
|
||||||
assert_eq!(chapters[2].title, "Chapter 3");
|
assert_eq!(chapters[2].title, "Chapter 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── strip_html tests ──
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_removes_tags() {
|
||||||
|
assert_eq!(strip_html("<p>Hello World</p>"), "Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_collapses_whitespace() {
|
||||||
|
assert_eq!(strip_html("<p>Hello World</p>"), "Hello World");
|
||||||
|
assert_eq!(strip_html("<div>\n Line 1\n Line 2\n</div>"), "Line 1 Line 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_handles_nested_tags() {
|
||||||
|
assert_eq!(strip_html("<div><p><b>Bold</b> text</p></div>"), "Bold text");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_handles_self_closing_tags() {
|
||||||
|
assert_eq!(strip_html("Text<br/>more<br />text"), "Textmoretext");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_handles_attributes() {
|
||||||
|
assert_eq!(strip_html("<p class=\"intro\" id='p1'>Hello</p>"), "Hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_empty_input() {
|
||||||
|
assert_eq!(strip_html(""), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_strip_html_plain_text_unchanged() {
|
||||||
|
assert_eq!(strip_html("Plain text, no HTML tags."), "Plain text, no HTML tags.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── extract_epub_chapter_texts tests ──
|
||||||
|
|
||||||
|
fn epub_with_chapter_text(title: &str, chapters: &[(&str, &str)]) -> Vec<u8> {
|
||||||
|
let mut buf = std::io::Cursor::new(Vec::new());
|
||||||
|
{
|
||||||
|
let mut zip = zip::ZipWriter::new(&mut buf);
|
||||||
|
let opts = zip::write::SimpleFileOptions::default()
|
||||||
|
.compression_method(zip::CompressionMethod::Stored);
|
||||||
|
|
||||||
|
zip.start_file("mimetype", opts).unwrap();
|
||||||
|
zip.write_all(b"application/epub+zip").unwrap();
|
||||||
|
|
||||||
|
zip.start_file("META-INF/container.xml", opts).unwrap();
|
||||||
|
zip.write_all(
|
||||||
|
b"<?xml version=\"1.0\"?>\n<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">\n <rootfiles>\n <rootfile full-path=\"OEBPS/content.opf\" media-type=\"application/oebps-package+xml\"/>\n </rootfiles>\n</container>"
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let mut opf = format!(
|
||||||
|
"<?xml version=\"1.0\"?>\n<package xmlns=\"http://www.idpf.org/2007/opf\" version=\"2.0\">\n<metadata xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n <dc:title>{}</dc:title>\n</metadata>\n<manifest>\n <item id=\"ncx\" href=\"toc.ncx\" media-type=\"application/x-dtbncx+xml\"/>\n",
|
||||||
|
title
|
||||||
|
);
|
||||||
|
for (i, (href, _)) in chapters.iter().enumerate() {
|
||||||
|
opf.push_str(&format!(" <item id=\"ch{}\" href=\"{}\" media-type=\"application/xhtml+xml\"/>\n", i, href));
|
||||||
|
}
|
||||||
|
opf.push_str("</manifest>\n<spine toc=\"ncx\">\n");
|
||||||
|
for i in 0..chapters.len() {
|
||||||
|
opf.push_str(&format!(" <itemref idref=\"ch{}\"/>\n", i));
|
||||||
|
}
|
||||||
|
opf.push_str("</spine>\n</package>");
|
||||||
|
zip.start_file("OEBPS/content.opf", opts).unwrap();
|
||||||
|
zip.write_all(opf.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let mut ncx = String::from("<?xml version=\"1.0\"?>\n<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\">\n<navMap>\n");
|
||||||
|
for (i, (href, _)) in chapters.iter().enumerate() {
|
||||||
|
ncx.push_str(&format!(
|
||||||
|
" <navPoint id=\"nav{}\" playOrder=\"{}\">\n <navLabel><text>Ch {}</text></navLabel>\n <content src=\"{}\"/>\n </navPoint>\n",
|
||||||
|
i, i + 1, i + 1, href
|
||||||
|
));
|
||||||
|
}
|
||||||
|
ncx.push_str("</navMap>\n</ncx>");
|
||||||
|
zip.start_file("toc.ncx", opts).unwrap();
|
||||||
|
zip.write_all(ncx.as_bytes()).unwrap();
|
||||||
|
|
||||||
|
for (href, content) in chapters {
|
||||||
|
zip.start_file(*href, opts).unwrap();
|
||||||
|
zip.write_all(content.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
zip.finish().unwrap();
|
||||||
|
}
|
||||||
|
buf.into_inner()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_epub_chapter_texts_with_html() {
|
||||||
|
let data = epub_with_chapter_text("Test", &[
|
||||||
|
("OEBPS/ch1.xhtml", "<html><body><p>Chapter one content.</p></body></html>"),
|
||||||
|
("OEBPS/ch2.xhtml", "<html><body><h1>Title</h1><p>Chapter <b>two</b>.</p></body></html>"),
|
||||||
|
]);
|
||||||
|
let path = write_temp(&data, "chapter_text.epub");
|
||||||
|
let texts = extract_epub_chapter_texts(&path).unwrap();
|
||||||
|
assert_eq!(texts.len(), 2);
|
||||||
|
assert_eq!(texts[0].text, "Chapter one content.");
|
||||||
|
assert_eq!(texts[1].text, "TitleChapter two.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_epub_chapter_texts_empty_chapter_filtered() {
|
||||||
|
let data = epub_with_chapter_text("Empty", &[
|
||||||
|
("OEBPS/ch1.xhtml", "<html><body></body></html>"),
|
||||||
|
("OEBPS/ch2.xhtml", "<html><body><p>Not empty</p></body></html>"),
|
||||||
|
]);
|
||||||
|
let path = write_temp(&data, "empty_ch.epub");
|
||||||
|
let texts = extract_epub_chapter_texts(&path).unwrap();
|
||||||
|
assert_eq!(texts.len(), 1);
|
||||||
|
assert_eq!(texts[0].text, "Not empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_epub_chapter_texts_all_empty() {
|
||||||
|
let data = epub_with_chapter_text("AllEmpty", &[
|
||||||
|
("OEBPS/ch1.xhtml", "<html/>"),
|
||||||
|
]);
|
||||||
|
let path = write_temp(&data, "all_empty.epub");
|
||||||
|
let texts = extract_epub_chapter_texts(&path).unwrap();
|
||||||
|
assert!(texts.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_epub_chapter_texts_plain_text_preserved() {
|
||||||
|
let data = epub_with_chapter_text("Plain", &[
|
||||||
|
("OEBPS/ch1.xhtml", "No HTML tags, just plain text."),
|
||||||
|
]);
|
||||||
|
let path = write_temp(&data, "plain.epub");
|
||||||
|
let texts = extract_epub_chapter_texts(&path).unwrap();
|
||||||
|
assert_eq!(texts.len(), 1);
|
||||||
|
assert_eq!(texts[0].text, "No HTML tags, just plain text.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user