use std::path::PathBuf;
use farmfe_core::{
module::{
meta_data::script::ScriptModuleMetaData,
module_graph::{ModuleGraph, ModuleGraphEdgeDataItem},
module_group::{ModuleGroup, ModuleGroupGraph, ModuleGroupId, ModuleGroupType},
Module, ModuleMetaData, ModuleType,
},
plugin::ResolveKind,
relative_path::RelativePath,
wax::Glob,
HashMap,
};
pub mod assert;
pub use insta;
use insta::Settings;
pub struct InstaHelper {}
impl InstaHelper {
pub fn create_setting() -> Settings {
let mut setting = Settings::clone_current();
setting.set_sort_maps(true);
setting.set_omit_expression(true);
setting.set_input_file(file!());
setting.set_prepend_module_to_snapshot(false);
setting
}
}
#[macro_export]
macro_rules! assert_debug_snapshot {
($ex:expr) => {
farmfe_testing_helpers::InstaHelper::create_setting()
.bind(|| farmfe_testing_helpers::insta::assert_debug_snapshot!($ex));
};
}
#[macro_export]
macro_rules! assert_snapshot {
($ex:expr) => {
farmfe_testing_helpers::InstaHelper::create_setting()
.bind(|| farmfe_testing_helpers::insta::assert_snapshot!($ex));
};
}
pub fn is_update_snapshot_from_env() -> bool {
std::env::var("FARM_UPDATE_SNAPSHOTS").is_ok() || std::env::var("INSTA_UPDATE").is_ok()
}
pub fn construct_test_module_graph() -> ModuleGraph {
let module_ids = vec!["A", "B", "C", "D", "E", "F", "G"]
.into_iter()
.map(|i| i.into());
let mut graph = ModuleGraph::new();
for id in module_ids {
let mut m = Module::new(id);
m.module_type = ModuleType::Js;
m.meta = Box::new(ModuleMetaData::Script(Box::new(
ScriptModuleMetaData::default(),
)));
graph.add_module(m);
}
let static_edges = vec![("A", "C", 0), ("B", "D", 0), ("B", "E", 1)];
let dynamic_edges = vec![("A", "D", 1), ("C", "F", 0), ("D", "F", 0), ("E", "G", 0)];
for (from, to, order) in static_edges {
graph
.add_edge_item(
&from.into(),
&to.into(),
ModuleGraphEdgeDataItem {
source: format!("./{to}"),
kind: ResolveKind::Import,
order,
},
)
.unwrap();
}
for (from, to, order) in dynamic_edges {
graph
.add_edge_item(
&from.into(),
&to.into(),
ModuleGraphEdgeDataItem {
source: format!("./{to}"),
kind: ResolveKind::DynamicImport,
order,
},
)
.unwrap();
}
graph
.add_edge_item(
&"F".into(),
&"A".into(),
ModuleGraphEdgeDataItem {
source: "./A".to_string(),
kind: ResolveKind::Import,
order: 0,
},
)
.unwrap();
graph.entries =
HashMap::from_iter([("A".into(), "A".to_string()), ("B".into(), "B".to_string())]);
graph
}
pub fn construct_test_module_group_graph() -> ModuleGroupGraph {
let mut module_group_graph = ModuleGroupGraph::new();
let mut module_group_a = ModuleGroup::new("A".into(), ModuleGroupType::Entry);
let module_group_a_id = module_group_a.id.clone();
module_group_a.add_module("A".into());
module_group_a.add_module("C".into());
module_group_graph.add_module_group(module_group_a);
let mut module_group_b = ModuleGroup::new("B".into(), ModuleGroupType::Entry);
let module_group_b_id = module_group_b.id.clone();
module_group_b.add_module("B".into());
module_group_b.add_module("D".into());
module_group_b.add_module("E".into());
module_group_graph.add_module_group(module_group_b);
let mut module_group_d = ModuleGroup::new("D".into(), ModuleGroupType::DynamicImport);
let module_group_d_id = module_group_d.id.clone();
module_group_d.add_module("D".into());
module_group_graph.add_module_group(module_group_d);
let mut module_group_f = ModuleGroup::new("F".into(), ModuleGroupType::DynamicImport);
let module_group_f_id = module_group_f.id.clone();
module_group_f.add_module("F".into());
module_group_f.add_module("A".into());
module_group_f.add_module("C".into());
module_group_graph.add_module_group(module_group_f);
let mut module_group_g = ModuleGroup::new("G".into(), ModuleGroupType::DynamicImport);
let module_group_g_id = module_group_g.id.clone();
module_group_g.add_module("G".into());
module_group_graph.add_module_group(module_group_g);
let edges = vec![
(module_group_a_id.clone(), module_group_d_id.clone()),
(module_group_a_id.clone(), module_group_f_id.clone()),
(module_group_d_id.clone(), module_group_f_id.clone()),
(module_group_b_id.clone(), module_group_f_id.clone()),
(module_group_b_id.clone(), module_group_g_id.clone()),
(module_group_f_id.clone(), module_group_d_id.clone()),
(module_group_f_id.clone(), module_group_f_id.clone()),
];
for (from, to) in edges {
module_group_graph.add_edge(&from, &to);
}
module_group_graph
}
pub fn construct_test_module_graph_complex() -> ModuleGraph {
let mut test_module_graph = construct_test_module_graph();
let mut module_h = Module::new("H".into());
module_h.module_type = ModuleType::Js;
test_module_graph.add_module(module_h);
let static_edges = vec![("D", "H", 1), ("F", "H", 0), ("G", "H", 0)];
for (from, to, order) in static_edges {
test_module_graph
.add_edge_item(
&from.into(),
&to.into(),
ModuleGraphEdgeDataItem {
source: format!("./{to}"),
kind: ResolveKind::Import,
order,
},
)
.unwrap();
}
test_module_graph.update_execution_order_for_modules();
test_module_graph
}
pub fn construct_test_module_group_graph_complex() -> ModuleGroupGraph {
let mut module_group_graph = construct_test_module_group_graph();
let module_group_b = module_group_graph
.module_group_mut(&ModuleGroupId::new(&"B".into(), &ModuleGroupType::Entry))
.unwrap();
module_group_b.add_module("H".into());
let module_group_d = module_group_graph
.module_group_mut(&ModuleGroupId::new(
&"D".into(),
&ModuleGroupType::DynamicImport,
))
.unwrap();
module_group_d.add_module("H".into());
let module_group_f = module_group_graph
.module_group_mut(&ModuleGroupId::new(
&"F".into(),
&ModuleGroupType::DynamicImport,
))
.unwrap();
module_group_f.add_module("H".into());
let module_group_g = module_group_graph
.module_group_mut(&ModuleGroupId::new(
&"G".into(),
&ModuleGroupType::DynamicImport,
))
.unwrap();
module_group_g.add_module("H".into());
module_group_graph
}
pub fn fixture<F>(pattern: &str, mut op: F)
where
F: FnMut(PathBuf, PathBuf),
{
let base_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let glob = Glob::new(pattern).unwrap();
for path in glob.walk(base_dir.clone()).flatten() {
op(path.path().to_path_buf(), base_dir.clone());
}
}
#[macro_export]
macro_rules! fixture {
($pattern:expr, $op:expr) => {
if cfg!(debug_assertions) {
farmfe_testing_helpers::fixture_debug($pattern, file!(), $op);
return;
}
farmfe_testing_helpers::fixture($pattern, $op);
};
}
pub fn fixture_debug<F>(pattern: &str, test_file_path: &str, mut op: F)
where
F: FnMut(PathBuf, PathBuf),
{
let mut file_path =
RelativePath::new(test_file_path).to_logical_path(std::env::current_dir().unwrap());
while let Some(parent) = file_path.parent() {
if parent.join("Cargo.toml").exists() {
break;
}
file_path = parent.to_path_buf();
}
if file_path.parent().is_none() {
panic!("can't find Cargo.toml");
}
let base_dir = file_path.parent().unwrap().to_path_buf();
let glob = Glob::new(pattern).unwrap();
let mut exists = false;
for path in glob.walk(base_dir.clone()).flatten() {
exists = true;
op(path.path().to_path_buf(), base_dir.clone());
}
if !exists {
panic!("no fixtures found under {pattern}");
}
}