mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
Expand roundtrip apkg test
This commit is contained in:
parent
bb27eb3f08
commit
ed24fd13db
2 changed files with 137 additions and 39 deletions
|
@ -3,50 +3,147 @@
|
|||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::path::Path;
|
||||
use std::{collections::HashSet, fs::File, io::Write};
|
||||
|
||||
use tempfile::tempdir;
|
||||
use crate::{
|
||||
media::files::sha1_of_data, prelude::*, search::SearchNode, tests::open_fs_test_collection,
|
||||
};
|
||||
|
||||
use crate::{collection::CollectionBuilder, media::MediaManager, prelude::*, search::SearchNode};
|
||||
|
||||
fn collection_with_media(dir: &Path, name: &str) -> Result<Collection> {
|
||||
let name = format!("{name}_src");
|
||||
let media_folder = dir.join(format!("{name}.media"));
|
||||
std::fs::create_dir(&media_folder)?;
|
||||
// add collection with sentinel note
|
||||
let mut col = CollectionBuilder::new(dir.join(format!("{name}.anki2")))
|
||||
.set_media_paths(media_folder, dir.join(format!("{name}.mdb")))
|
||||
.build()?;
|
||||
let nt = col.get_notetype_by_name("Basic")?.unwrap();
|
||||
let mut note = nt.new_note();
|
||||
col.add_note(&mut note, DeckId(1))?;
|
||||
// add sample media
|
||||
let mgr = MediaManager::new(&col.media_folder, &col.media_db)?;
|
||||
let mut ctx = mgr.dbctx();
|
||||
mgr.add_file(&mut ctx, "1", b"1")?;
|
||||
mgr.add_file(&mut ctx, "2", b"2")?;
|
||||
mgr.add_file(&mut ctx, "3", b"3")?;
|
||||
Ok(col)
|
||||
}
|
||||
const SAMPLE_JPG: &str = "sample.jpg";
|
||||
const SAMPLE_MP3: &str = "sample.mp3";
|
||||
const SAMPLE_JS: &str = "_sample.js";
|
||||
const JPG_DATA: &[u8] = b"1";
|
||||
const MP3_DATA: &[u8] = b"2";
|
||||
const JS_DATA: &[u8] = b"3";
|
||||
const OTHER_MP3_DATA: &[u8] = b"4";
|
||||
|
||||
#[test]
|
||||
fn roundtrip() -> Result<()> {
|
||||
let _dir = tempdir()?;
|
||||
let dir = _dir.path();
|
||||
const NAME: &str = "mycol";
|
||||
fn roundtrip() {
|
||||
let (mut src_col, src_tempdir) = open_fs_test_collection("src");
|
||||
let (mut target_col, _target_tempdir) = open_fs_test_collection("target");
|
||||
let apkg_path = src_tempdir.path().join("test.apkg");
|
||||
|
||||
let mut col = collection_with_media(dir, NAME)?;
|
||||
let apkg_path = dir.join(format!("{NAME}.apkg"));
|
||||
let (main_deck, sibling_deck) = src_col.add_sample_decks();
|
||||
let notetype = src_col.add_sample_notetype();
|
||||
let note = src_col.add_sample_note(&main_deck, &sibling_deck, ¬etype);
|
||||
src_col.add_sample_media();
|
||||
target_col.add_conflicting_media();
|
||||
|
||||
col.export_apkg(
|
||||
&apkg_path,
|
||||
SearchNode::WholeCollection,
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
|_| (),
|
||||
)?;
|
||||
col.import_apkg(&apkg_path)?;
|
||||
src_col
|
||||
.export_apkg(
|
||||
&apkg_path,
|
||||
SearchNode::from_deck_name("parent::sample"),
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
|_| (),
|
||||
)
|
||||
.unwrap();
|
||||
target_col.import_apkg(&apkg_path, |_| Ok(())).unwrap();
|
||||
|
||||
Ok(())
|
||||
target_col.assert_decks();
|
||||
target_col.assert_notetype(¬etype);
|
||||
target_col.assert_note_and_media(¬e);
|
||||
|
||||
target_col.undo().unwrap();
|
||||
target_col.assert_empty();
|
||||
}
|
||||
|
||||
impl Collection {
|
||||
fn add_sample_decks(&mut self) -> (Deck, Deck) {
|
||||
let sample = self.add_named_deck("parent\x1fsample");
|
||||
self.add_named_deck("parent\x1fsample\x1fchild");
|
||||
let siblings = self.add_named_deck("siblings");
|
||||
|
||||
(sample, siblings)
|
||||
}
|
||||
|
||||
fn add_named_deck(&mut self, name: &str) -> Deck {
|
||||
let mut deck = Deck::new_normal();
|
||||
deck.name = NativeDeckName::from_native_str(name);
|
||||
self.add_deck(&mut deck).unwrap();
|
||||
deck
|
||||
}
|
||||
|
||||
fn add_sample_notetype(&mut self) -> Notetype {
|
||||
let mut nt = Notetype {
|
||||
name: "sample".into(),
|
||||
..Default::default()
|
||||
};
|
||||
nt.add_field("sample");
|
||||
nt.add_template("sample1", "{{sample}}", "<script src=_sample.js></script>");
|
||||
nt.add_template("sample2", "{{sample}}2", "");
|
||||
self.add_notetype(&mut nt, true).unwrap();
|
||||
nt
|
||||
}
|
||||
|
||||
fn add_sample_note(
|
||||
&mut self,
|
||||
main_deck: &Deck,
|
||||
sibling_decks: &Deck,
|
||||
notetype: &Notetype,
|
||||
) -> Note {
|
||||
let mut sample = notetype.new_note();
|
||||
sample.fields_mut()[0] = format!("<img src='{SAMPLE_JPG}'> [sound:{SAMPLE_MP3}]");
|
||||
sample.tags = vec!["sample".into()];
|
||||
self.add_note(&mut sample, main_deck.id).unwrap();
|
||||
|
||||
let card = self
|
||||
.storage
|
||||
.get_card_by_ordinal(sample.id, 1)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
self.set_deck(&[card.id], sibling_decks.id).unwrap();
|
||||
|
||||
sample
|
||||
}
|
||||
|
||||
fn add_sample_media(&self) {
|
||||
self.add_media(&[
|
||||
(SAMPLE_JPG, JPG_DATA),
|
||||
(SAMPLE_MP3, MP3_DATA),
|
||||
(SAMPLE_JS, JS_DATA),
|
||||
]);
|
||||
}
|
||||
|
||||
fn add_conflicting_media(&mut self) {
|
||||
let mut file = File::create(self.media_folder.join(SAMPLE_MP3)).unwrap();
|
||||
file.write_all(OTHER_MP3_DATA).unwrap();
|
||||
}
|
||||
|
||||
fn assert_decks(&mut self) {
|
||||
let existing_decks: HashSet<_> = self
|
||||
.get_all_deck_names(true)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|(_, name)| name)
|
||||
.collect();
|
||||
for deck in ["parent", "parent::sample", "siblings"] {
|
||||
assert!(existing_decks.contains(deck));
|
||||
}
|
||||
assert!(!existing_decks.contains("parent::sample::child"));
|
||||
}
|
||||
|
||||
fn assert_notetype(&mut self, notetype: &Notetype) {
|
||||
assert!(self.get_notetype(notetype.id).unwrap().is_some());
|
||||
}
|
||||
|
||||
fn assert_note_and_media(&mut self, note: &Note) {
|
||||
let sha1 = sha1_of_data(MP3_DATA);
|
||||
let new_mp3_name = format!("sample-{}.mp3", hex::encode(&sha1));
|
||||
|
||||
for file in [SAMPLE_JPG, SAMPLE_JS, &new_mp3_name] {
|
||||
assert!(self.media_folder.join(file).exists())
|
||||
}
|
||||
|
||||
let imported_note = self.storage.get_note(note.id).unwrap().unwrap();
|
||||
assert!(imported_note.fields()[0].contains(&new_mp3_name));
|
||||
}
|
||||
|
||||
fn assert_empty(&self) {
|
||||
assert!(self.get_all_deck_names(true).unwrap().is_empty());
|
||||
assert!(self.storage.get_all_note_ids().unwrap().is_empty());
|
||||
assert!(self.storage.get_all_card_ids().unwrap().is_empty());
|
||||
assert!(self.storage.all_tags().unwrap().is_empty());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ mod sync;
|
|||
pub mod tags;
|
||||
pub mod template;
|
||||
pub mod template_filters;
|
||||
pub(crate) mod tests;
|
||||
pub mod text;
|
||||
pub mod timestamp;
|
||||
pub mod types;
|
||||
|
|
Loading…
Reference in a new issue