use super::common::{create_config, fixture_path};
#[test]
fn detects_real_three_hop_chain() {
let root = fixture_path("prop-drilling");
let mut config = create_config(root);
config.rules.prop_drilling = fallow_config::Severity::Warn;
let results = fallow_core::analyze(&config).expect("analysis should succeed");
let chains = &results.prop_drilling_chains;
assert_eq!(
chains.len(),
1,
"exactly one prop-drilling chain expected: {:?}",
chains
.iter()
.map(|c| (c.chain.prop.as_str(), c.chain.depth))
.collect::<Vec<_>>()
);
let chain = &chains[0].chain;
assert_eq!(chain.prop, "user", "the drilled prop is `user`");
assert!(chain.depth >= 3, "depth must be >= 3: {}", chain.depth);
assert_eq!(chain.depth as usize, chain.hops.len(), "depth == hop count");
let components: Vec<&str> = chain.hops.iter().map(|h| h.component.as_str()).collect();
assert_eq!(
components,
vec!["Page", "Layout", "Sidebar", "Profile"],
"the located hop trail runs source -> pass -> pass -> consumer"
);
for hop in &chain.hops {
assert!(hop.line >= 1, "every hop has a 1-based line: {hop:?}");
let stem = hop
.file
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or_default();
assert_eq!(
stem, hop.component,
"each hop file is the component's module: {hop:?}"
);
}
}
#[test]
fn abstains_on_every_ladder_case() {
let root = fixture_path("prop-drilling-abstain");
let mut config = create_config(root);
config.rules.prop_drilling = fallow_config::Severity::Warn;
let results = fallow_core::analyze(&config).expect("analysis should succeed");
assert!(
results.prop_drilling_chains.is_empty(),
"every abstain case must yield zero chains: {:?}",
results
.prop_drilling_chains
.iter()
.map(|c| {
(
c.chain.prop.clone(),
c.chain
.hops
.iter()
.map(|h| h.component.clone())
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>()
);
}
#[test]
fn dormant_when_rule_off() {
let root = fixture_path("prop-drilling");
let config = create_config(root); let results = fallow_core::analyze(&config).expect("analysis should succeed");
assert!(
results.prop_drilling_chains.is_empty(),
"the prop-drilling rule is off by default: {:?}",
results.prop_drilling_chains.len()
);
}
#[test]
fn dep_gated_to_react() {
let root = fixture_path("unused-component-prop");
let mut config = create_config(root);
config.rules.prop_drilling = fallow_config::Severity::Warn;
let results = fallow_core::analyze(&config).expect("analysis should succeed");
assert!(
results.prop_drilling_chains.is_empty(),
"prop-drilling must not fire on a non-React project"
);
}