use crate::{
commands::Commands,
format_context::FormatContext,
render_context::RenderContext,
renderer::{OutputMode, render},
request::Request,
};
use ferritin_common::{
Navigator,
sources::{LocalSource, StdSource},
};
use ratatui::backend::TestBackend;
use std::path::PathBuf;
fn get_fixture_crate_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../tests/fixture-crate")
}
fn create_test_state() -> Request {
let navigator = Navigator::default()
.with_local_source(LocalSource::load(&get_fixture_crate_path()).ok())
.with_std_source(StdSource::from_rustup());
Request::new(navigator, FormatContext::new())
}
fn convert_osc8_to_markdown(text: &str) -> String {
use regex::Regex;
let re = Regex::new("\x1B\\]8;;([^\x1B]*)\x1B\\\\(.*?)\x1B\\]8;;\x1B\\\\").unwrap();
re.replace_all(text, "[$2]($1)").to_string()
}
fn render_for_tests(command: Commands, output_mode: OutputMode) -> String {
let request = create_test_state();
let (document, _, _) = command.execute(&request);
let mut output = String::new();
let render_context = RenderContext::new().with_output_mode(output_mode);
render(&document, &render_context, &mut output).unwrap();
let output = if matches!(output_mode, OutputMode::Tty) {
let with_markdown_links = convert_osc8_to_markdown(&output);
String::from_utf8(strip_ansi_escapes::strip(with_markdown_links.as_bytes()))
.unwrap_or(with_markdown_links)
} else {
output
};
let fixture_crate_path = get_fixture_crate_path();
let fixture_crate_path_str = fixture_crate_path
.canonicalize()
.unwrap_or(fixture_crate_path)
.to_string_lossy()
.to_string();
let output = output.replace(&fixture_crate_path_str, "/TEST_CRATE_ROOT");
let re =
regex::Regex::new(r"\d+\.\d+\.\d+-[a-z]+\s+\([a-f0-9]+\s+\d{4}-\d{2}-\d{2}\)").unwrap();
re.replace_all(&output, "RUST_VERSION").to_string()
}
fn render_interactive_for_tests(command: Commands) -> TestBackend {
use crate::renderer::render_to_test_backend;
let request = create_test_state();
let (document, _, _) = command.execute(&request);
let render_context = RenderContext::new();
render_to_test_backend(document, render_context)
}
macro_rules! test_all_modes {
($name:ident, $cmd:expr) => {
paste::paste! {
#[test]
fn [<$name _test_mode>]() {
insta::assert_snapshot!(render_for_tests($cmd, OutputMode::TestMode));
}
#[test]
fn [<$name _tty_mode>]() {
insta::assert_snapshot!(render_for_tests($cmd, OutputMode::Tty));
}
#[test]
fn [<$name _plain_mode>]() {
insta::assert_snapshot!(render_for_tests($cmd, OutputMode::Plain));
}
#[test]
fn [<$name _ai_mode>]() {
insta::assert_snapshot!(render_for_tests($cmd, OutputMode::Ai));
}
#[test]
fn [<$name _interactive_mode>]() {
let fixture_crate_path = get_fixture_crate_path();
let fixture_crate_path_str = fixture_crate_path
.canonicalize()
.unwrap_or(fixture_crate_path)
.to_string_lossy()
.to_string();
let mut settings = insta::Settings::clone_current();
settings.add_filter(&fixture_crate_path_str, "/TEST_CRATE_ROOT");
settings.add_filter(r#"(?m)(.*TEST_CRATE_ROOT[^"]+?)\s+"$"#, r#"$1""#);
settings.add_filter(r"\d+\.\d+\.\d+-[a-z]+\s+\([a-f0-9]+\s+\d{4}-\d{2}-\d{2}\)", "RUST_VERSION");
settings.bind(|| {
insta::assert_snapshot!(render_interactive_for_tests($cmd));
});
}
}
};
}
test_all_modes!(get_crate_root, Commands::get("crate"));
test_all_modes!(get_struct_details, Commands::get("crate::TestStruct"));
test_all_modes!(
get_struct_with_source,
Commands::get("crate::TestStruct").with_source()
);
test_all_modes!(get_submodule, Commands::get("crate::submodule"));
test_all_modes!(
get_enum_details,
Commands::get("crate::submodule::TestEnum")
);
test_all_modes!(get_generic_enum, Commands::get("crate::GenericEnum"));
test_all_modes!(nonexistent_item, Commands::get("crate::DoesNotExist"));
test_all_modes!(recursive_module_listing, Commands::get("crate").recursive());
test_all_modes!(
recursive_submodule_listing,
Commands::get("crate::submodule").recursive()
);
test_all_modes!(
get_item_with_normalized_crate_name,
Commands::get("fixture-crate::TestStruct")
);
test_all_modes!(list_crates, Commands::list());
test_all_modes!(search, Commands::search("trigger line-based truncation"));
test_all_modes!(search_2, Commands::search("generic struct"));
test_all_modes!(
fuzzy_matching_typo,
Commands::get("crate::TestStruct::test_metod")
);
test_all_modes!(
fuzzy_matching_trait_methods,
Commands::get("crate::TestStruct::cute")
);
test_all_modes!(
fuzzy_matching_suggestions,
Commands::get("crate::TestStruct::incrementCount")
);
test_all_modes!(get_std, Commands::get("std"));
test_all_modes!(
get_markdown_test,
Commands::get("fixture-crate::markdown_test")
);
test_all_modes!(get_trait_simple, Commands::get("crate::TestTrait"));
test_all_modes!(get_trait_complex, Commands::get("crate::ComplexTrait"));