Skip to content

Commit 8eab1ae

Browse files
liangmiQwQclaude
andcommitted
test(js-executor): add unit tests for Node.js version compatibility check
Cover check_runtime_compatibility (compatible, v-prefixed, incompatible, system, unparseable version, invalid requirement range) and get_cli_engines_requirement (reads engines.node from package.json, returns None when package.json is missing). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 72990ab commit 8eab1ae

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

crates/vite_global_cli/src/js_executor.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,122 @@ mod tests {
526526
assert_eq!(cmd.as_std().get_program(), OsStr::new(expected_program));
527527
}
528528

529+
// ---- check_runtime_compatibility ----
530+
531+
fn make_runtime_with_version(version: &str) -> JsRuntime {
532+
let binary_path = if cfg!(windows) {
533+
AbsolutePathBuf::new("C:\\node\\node.exe".into()).unwrap()
534+
} else {
535+
AbsolutePathBuf::new("/usr/local/bin/node".into()).unwrap()
536+
};
537+
let mut runtime = JsRuntime::from_system(JsRuntimeType::Node, binary_path);
538+
runtime.version = version.into();
539+
runtime
540+
}
541+
542+
#[test]
543+
fn compatible_version_passes() {
544+
let runtime = make_runtime_with_version("22.12.0");
545+
assert!(
546+
check_runtime_compatibility(&runtime, "^20.19.0 || >=22.12.0").is_ok(),
547+
"22.12.0 should satisfy ^20.19.0 || >=22.12.0"
548+
);
549+
}
550+
551+
#[test]
552+
fn compatible_version_with_v_prefix_passes() {
553+
let runtime = make_runtime_with_version("v20.19.0");
554+
assert!(
555+
check_runtime_compatibility(&runtime, "^20.19.0 || >=22.12.0").is_ok(),
556+
"v20.19.0 should satisfy ^20.19.0 || >=22.12.0"
557+
);
558+
}
559+
560+
#[test]
561+
fn incompatible_version_returns_error() {
562+
let runtime = make_runtime_with_version("18.0.0");
563+
let err = check_runtime_compatibility(&runtime, "^20.19.0 || >=22.12.0")
564+
.expect_err("18.0.0 should not satisfy ^20.19.0 || >=22.12.0");
565+
assert!(
566+
matches!(err, Error::NodeVersionIncompatible { .. }),
567+
"expected NodeVersionIncompatible, got {err:?}"
568+
);
569+
}
570+
571+
#[test]
572+
fn system_runtime_skips_check() {
573+
// from_system() sets version == "system"
574+
let binary_path = if cfg!(windows) {
575+
AbsolutePathBuf::new("C:\\node\\node.exe".into()).unwrap()
576+
} else {
577+
AbsolutePathBuf::new("/usr/local/bin/node".into()).unwrap()
578+
};
579+
let runtime = JsRuntime::from_system(JsRuntimeType::Node, binary_path);
580+
assert_eq!(runtime.version(), "system");
581+
assert!(
582+
check_runtime_compatibility(&runtime, "^20.19.0 || >=22.12.0").is_ok(),
583+
"system runtime should pass the check unconditionally"
584+
);
585+
}
586+
587+
#[test]
588+
fn unparseable_version_skips_check() {
589+
let runtime = make_runtime_with_version("not-a-version");
590+
assert!(
591+
check_runtime_compatibility(&runtime, "^20.19.0 || >=22.12.0").is_ok(),
592+
"unparseable version should not cause an error"
593+
);
594+
}
595+
596+
#[test]
597+
fn invalid_requirement_skips_check() {
598+
let runtime = make_runtime_with_version("18.0.0");
599+
assert!(
600+
check_runtime_compatibility(&runtime, "not-a-range").is_ok(),
601+
"invalid requirement range should not cause an error"
602+
);
603+
}
604+
605+
// ---- get_cli_engines_requirement ----
606+
607+
#[tokio::test]
608+
async fn get_cli_engines_requirement_reads_from_package_json() {
609+
use std::io::Write;
610+
611+
use tempfile::TempDir;
612+
613+
let temp_dir = TempDir::new().unwrap();
614+
// The scripts dir is `<pkg_dir>/dist`, and get_cli_package_dir returns its parent.
615+
let dist_dir = temp_dir.path().join("dist");
616+
std::fs::create_dir(&dist_dir).unwrap();
617+
618+
let pkg_json_content = r#"{ "engines": { "node": "^20.19.0 || >=22.12.0" } }"#;
619+
let mut f = std::fs::File::create(temp_dir.path().join("package.json")).unwrap();
620+
f.write_all(pkg_json_content.as_bytes()).unwrap();
621+
622+
let scripts_dir = AbsolutePathBuf::new(dist_dir).unwrap();
623+
let executor = JsExecutor::new(Some(scripts_dir));
624+
625+
let req = executor.get_cli_engines_requirement().await;
626+
assert_eq!(req.as_deref(), Some("^20.19.0 || >=22.12.0"));
627+
}
628+
629+
#[tokio::test]
630+
async fn get_cli_engines_requirement_returns_none_when_missing() {
631+
use tempfile::TempDir;
632+
633+
let temp_dir = TempDir::new().unwrap();
634+
let dist_dir = temp_dir.path().join("dist");
635+
std::fs::create_dir(&dist_dir).unwrap();
636+
637+
// No package.json → should return None
638+
let scripts_dir = AbsolutePathBuf::new(dist_dir).unwrap();
639+
let executor = JsExecutor::new(Some(scripts_dir));
640+
641+
let req = executor.get_cli_engines_requirement().await;
642+
assert!(req.is_none());
643+
}
644+
529645
#[tokio::test]
530646
#[serial]
531647
async fn test_delegate_to_local_cli_prints_node_version() {

0 commit comments

Comments
 (0)