use super::*;
use crate::recipe::Recipe;
use crate::recipe::fetch::Index;
use crate::tui::data::library::LibraryEntry;
fn real_recipe() -> Recipe {
let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/recipes/qwen3.6/qwen3.6-35b-a3b-fp8-mtp.yaml");
let text = std::fs::read_to_string(&path).expect("fixture");
Recipe::parse("qwen3.6/flagship", &text).expect("parses")
}
fn with_weights(model: &str) -> LibraryEntry {
LibraryEntry {
id: model.into(),
snapshot_dir: Default::default(),
size_bytes: 1024,
has_weights: true,
model_type: "qwen3_6_moe".into(),
quant: "fp8".into(),
layers: 40,
hidden: 4096,
heads: 32,
experts: 128,
context: 65536,
optimized: true,
}
}
fn state_with_recipe() -> LibState {
let recipe = real_recipe();
let local = vec![with_weights(&recipe.model)];
let mut s = LibState {
index: Index {
recipes: vec![recipe],
..Index::default()
},
..LibState::default()
};
s.rebuild(&local);
s
}
#[test]
fn starting_a_recipe_whose_weights_are_missing_is_refused_before_anything_is_torn_down() {
let recipe = real_recipe();
let mut s = LibState {
index: Index {
recipes: vec![recipe],
..Index::default()
},
..LibState::default()
};
s.rebuild(&[]);
s.view = View::Config;
assert!(!s.selected_has_weights(), "nothing is on disk");
let err = s
.launch(std::sync::Arc::new(
crate::main_modules::model_host::ModelHost::empty(),
))
.expect_err("a model that is not downloaded cannot be started");
assert!(err.contains("not downloaded"), "{err}");
assert!(err.contains('d'), "and names the download key: {err}");
let mut ok = state_with_recipe();
ok.view = View::Config;
assert!(ok.selected_has_weights(), "the fixture has weights");
}
#[test]
fn the_download_advice_matches_the_number_of_escapes_it_actually_takes() {
use crossterm::event::{KeyCode, KeyEvent};
let mut s = state_with_recipe();
s.view = View::Config;
s.on_key(KeyEvent::from(KeyCode::Esc));
assert_eq!(s.view, View::Cards, "one Esc leaves the form");
let outcome = s.on_key(KeyEvent::from(KeyCode::Char('d')));
assert!(
matches!(outcome, crate::tui::lib_keys::Outcome::Download),
"d must start a download from the pane one Esc away from the form"
);
}
#[test]
fn the_download_keys_work_in_both_panes_that_show_a_model() {
use crossterm::event::{KeyCode, KeyEvent};
for view in [View::List, View::Cards] {
let mut s = state_with_recipe();
s.view = view;
for (key, want) in [
('d', crate::tui::lib_keys::Outcome::Download),
('x', crate::tui::lib_keys::Outcome::CancelDownload),
('u', crate::tui::lib_keys::Outcome::CheckFresh),
] {
let got = s.on_key(KeyEvent::from(KeyCode::Char(key)));
assert_eq!(
std::mem::discriminant(&got),
std::mem::discriminant(&want),
"{key:?} in {view:?}"
);
assert_eq!(s.view, view, "{key:?} must not navigate");
}
}
}