use super::{OutputLayout, default_binding_crate_root, relative_slash_path, resolve_output_layout};
use std::path::{Path, PathBuf};
#[test]
fn default_binding_crate_root_matches_every_scaffolder_suffix() {
let cases: &[(&str, Option<&str>)] = &[
("python", Some("crates/toolkit-py")),
("node", Some("crates/toolkit-node")),
("php", Some("crates/toolkit-php")),
("ffi", Some("crates/toolkit-ffi")),
("wasm", Some("crates/toolkit-wasm")),
("ruby", None),
("elixir", None),
("go", None),
("swift", None),
];
for (lang, expected) in cases {
assert_eq!(
default_binding_crate_root("toolkit", lang),
expected.map(str::to_string),
"default_binding_crate_root(\"toolkit\", {lang:?})"
);
}
}
#[test]
fn output_layout_derives_the_crate_root_from_the_path_shape() {
let cases: &[(&str, &str, &str)] = &[
(
"crates/toolkit-wasm/src/",
"crates/toolkit-wasm",
"crates/toolkit-wasm/src/",
),
(
"crates/toolkit-wasm/src",
"crates/toolkit-wasm",
"crates/toolkit-wasm/src",
),
("packages/wasm", "packages/wasm", "packages/wasm/src"),
("packages/wasm/", "packages/wasm/", "packages/wasm/src"),
(
"packages/ruby/ext/toolkit_rb/src",
"packages/ruby/ext/toolkit_rb",
"packages/ruby/ext/toolkit_rb/src",
),
("src", "", "src"),
];
for (output_dir, expected_root, expected_src) in cases {
let layout = OutputLayout::from_output_dir(output_dir);
assert_eq!(
layout.root,
PathBuf::from(expected_root),
"crate root for output dir `{output_dir}`"
);
assert_eq!(
layout.src,
PathBuf::from(expected_src),
"source dir for output dir `{output_dir}`"
);
}
}
#[test]
fn output_layout_never_escapes_a_crate_root_shaped_path() {
for output_dir in [
"packages/wasm",
"packages/ffi",
"packages/php",
"packages/deeply/nested/pkg",
] {
let layout = OutputLayout::from_output_dir(output_dir);
assert_eq!(layout.root, PathBuf::from(output_dir), "root for `{output_dir}`");
assert!(
layout.src.starts_with(&layout.root),
"source dir `{}` must live inside crate root `{}`",
layout.src.display(),
layout.root.display()
);
}
}
#[test]
fn resolve_output_layout_falls_back_to_the_backend_default() {
let layout = resolve_output_layout(None, "toolkit", "crates/{name}-wasm/src/");
assert_eq!(layout.root, PathBuf::from("crates/toolkit-wasm"));
assert_eq!(layout.src, PathBuf::from("crates/toolkit-wasm/src/"));
}
#[test]
fn resolve_output_layout_prefers_the_configured_path() {
let configured = PathBuf::from("bindings/{name}-wasm");
let layout = resolve_output_layout(Some(&configured), "toolkit", "crates/{name}-wasm/src/");
assert_eq!(layout.root, PathBuf::from("bindings/toolkit-wasm"));
assert_eq!(layout.src, PathBuf::from("bindings/toolkit-wasm/src"));
}
#[test]
fn relative_slash_path_handles_root_flat_and_workspace_core_crates() {
let binding_root = Path::new("crates/toolkit-ffi");
assert_eq!(
relative_slash_path(binding_root, Path::new("")),
"../..",
"root-flat core crate: Cargo.toml sits at the project root"
);
assert_eq!(
relative_slash_path(binding_root, Path::new("crates/toolkit-core")),
"../toolkit-core",
"workspace-shaped core crate: Cargo.toml sits beside the binding crate"
);
}
#[test]
fn relative_slash_path_collapses_to_dot_for_identical_roots() {
let same = Path::new("crates/toolkit-ffi");
assert_eq!(relative_slash_path(same, same), ".");
}