use super::handle;
use crate::bin_cli::args::Commands;
use crate::bin_cli::dispatch::DispatchContext;
use crate::test_support::CwdGuard;
use tracing_test::traced_test;
const WIDGET_LIB_SOURCE: &str = r#"
pub fn always_present(value: i64) -> i64 {
value
}
/// Counts widgets in a collection. Only available when the `widgets` feature is enabled.
#[cfg(feature = "widgets")]
pub fn count_widgets(collection: String) -> Result<i64, String> {
Ok(collection.len() as i64)
}
"#;
const WIDGET_LIB_CARGO_TOML: &str = "[package]\nname = \"widget-lib\"\nversion = \"0.1.0\"\nedition = \"2024\"\n";
const WIDGET_LIB_ALEF_TOML: &str = r#"
[workspace]
languages = ["dart"]
[[crates]]
name = "widget-lib"
sources = ["src/lib.rs"]
version_from = "Cargo.toml"
[crates.dart]
package_name = "widget_lib"
skip_frb = true
"#;
const STALE_DART_RUST_CARGO_TOML: &str = "\
[package]
name = \"widget-lib-dart\"
version = \"0.1.0\"
edition = \"2024\"
[lib]
crate-type = [\"cdylib\", \"staticlib\"]
[dependencies]
flutter_rust_bridge = \"=2.0.0\"
";
const STALE_BRIDGE_DART: &str = "\
Future<int> alwaysPresent({required int value}) =>
RustLib.instance.api.crateAlwaysPresentAlwaysPresent(value: value);
";
fn write_widget_lib_fixture(root: &std::path::Path) {
std::fs::create_dir_all(root.join("src")).expect("create fixture src directory");
std::fs::write(root.join("src/lib.rs"), WIDGET_LIB_SOURCE).expect("write fixture source");
std::fs::write(root.join("Cargo.toml"), WIDGET_LIB_CARGO_TOML).expect("write fixture Cargo.toml");
std::fs::write(root.join("alef.toml"), WIDGET_LIB_ALEF_TOML).expect("write fixture alef.toml");
let rust_dir = root.join("packages/dart/rust");
std::fs::create_dir_all(&rust_dir).expect("create dart rust crate directory");
std::fs::write(rust_dir.join("Cargo.toml"), STALE_DART_RUST_CARGO_TOML).expect("seed stale dart Cargo.toml");
let bridge_dir = root.join("packages/dart/lib/src/widget_lib_bridge_generated");
std::fs::create_dir_all(&bridge_dir).expect("create bridge_generated directory");
std::fs::write(bridge_dir.join("lib.dart"), STALE_BRIDGE_DART).expect("seed stale bridge lib.dart");
}
fn widget_lib_all_command() -> Commands {
Commands::All {
clean: false,
clobber_create_once_seeds: false,
strict: false,
skip_frb: false,
skip_snippet_validation: false,
skip_compile: false,
}
}
#[test]
#[traced_test]
fn all_surfaces_the_refusal_report_before_a_post_build_coverage_failure() {
let temp = tempfile::tempdir().expect("tempdir");
let root = temp.path().canonicalize().unwrap_or_else(|_| temp.path().to_path_buf());
write_widget_lib_fixture(&root);
let _cwd = CwdGuard::enter(&root);
let context = DispatchContext {
config_path: root.join("alef.toml"),
crate_filter: Vec::new(),
};
let result = handle(widget_lib_all_command(), &context);
let error = match result {
Err(error) => error,
Ok(_) => panic!(
"a stale FRB bridge missing a cfg-gated facade function must still fail the run -- \
VerifyFrbBridgeCoverage's detection (alef #135) must not be weakened"
),
};
let message = format!("{error:#}");
assert!(
message.contains("count_widgets") && message.contains("missing 1 function"),
"the propagated error must still be VerifyFrbBridgeCoverage's own diagnostic naming the \
cfg-gated function: {message}"
);
assert!(
logs_contain("alef adopt"),
"the ownership guard refused packages/dart/rust/Cargo.toml (it predates alef's marker \
convention for .toml), which is *why* the bridge coverage check failed -- \
pipeline::report_refused_writes must run before the post-build error propagates, or an \
operator only ever sees VerifyFrbBridgeCoverage's misleading \"install/enable \
flutter_rust_bridge_codegen\" text and never learns the actual fix is `alef adopt`"
);
assert!(
logs_contain("Cargo.toml"),
"the surfaced refusal report must name the frozen file itself, not just announce that \
something was refused"
);
}