mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
2146 lines
68 KiB
Rust
2146 lines
68 KiB
Rust
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
|
|
use deno_core::serde_json;
|
|
use deno_core::serde_json::json;
|
|
use deno_core::serde_json::Value;
|
|
|
|
use pretty_assertions::assert_eq;
|
|
use test_util as util;
|
|
use test_util::itest;
|
|
use url::Url;
|
|
use util::assert_contains;
|
|
use util::env_vars_for_npm_tests;
|
|
use util::http_server;
|
|
use util::TestContextBuilder;
|
|
|
|
// NOTE: See how to make test npm packages at ./testdata/npm/README.md
|
|
|
|
// FIXME(bartlomieju): npm: specifiers are not handled in dynamic imports
|
|
// at the moment
|
|
// itest!(dynamic_import {
|
|
// args: "run --allow-read --allow-env npm/dynamic_import/main.ts",
|
|
// output: "npm/dynamic_import/main.out",
|
|
// envs: env_vars_for_npm_tests(),
|
|
// http_server: true,
|
|
// });
|
|
|
|
itest!(run_existing_npm_package {
|
|
args: "run --allow-read --node-modules-dir=auto npm:@denotest/bin",
|
|
output: "npm/run_existing_npm_package/main.out",
|
|
envs: env_vars_for_npm_tests(),
|
|
http_server: true,
|
|
temp_cwd: true,
|
|
cwd: Some("npm/run_existing_npm_package/"),
|
|
copy_temp_dir: Some("npm/run_existing_npm_package/"),
|
|
});
|
|
|
|
itest!(require_resolve_url_paths {
|
|
args: "run -A --quiet --node-modules-dir=auto url_paths.ts",
|
|
output: "npm/require_resolve_url/url_paths.out",
|
|
envs: env_vars_for_npm_tests(),
|
|
http_server: true,
|
|
exit_code: 0,
|
|
cwd: Some("npm/require_resolve_url/"),
|
|
copy_temp_dir: Some("npm/require_resolve_url/"),
|
|
});
|
|
#[test]
|
|
fn parallel_downloading() {
|
|
let (out, _err) = util::run_and_collect_output_with_args(
|
|
true,
|
|
vec![
|
|
"run",
|
|
"--allow-read",
|
|
"--allow-env",
|
|
"npm/cjs_with_deps/main.js",
|
|
],
|
|
None,
|
|
// don't use the sync env var
|
|
Some(env_vars_for_npm_tests()),
|
|
true,
|
|
);
|
|
assert!(out.contains("chalk cjs loads"));
|
|
}
|
|
|
|
#[test]
|
|
fn cached_only_after_first_run() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("npm/cached_only_after_first_run/main1.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--cached-only")
|
|
.arg("npm/cached_only_after_first_run/main2.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(
|
|
stderr,
|
|
"An npm specifier not found in cache: \"ansi-styles\", --cached-only is specified."
|
|
);
|
|
assert!(stdout.is_empty());
|
|
assert!(!output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--cached-only")
|
|
.arg("npm/cached_only_after_first_run/main1.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(output.status.success());
|
|
assert!(stderr.is_empty());
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
}
|
|
|
|
#[test]
|
|
fn reload_flag() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("npm/reload/main.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--reload")
|
|
.arg("npm/reload/main.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--reload=npm:")
|
|
.arg("npm/reload/main.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--reload=npm:chalk")
|
|
.arg("npm/reload/main.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--reload=npm:foobar")
|
|
.arg("npm/reload/main.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stderr.is_empty());
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn no_npm_after_first_run() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--no-npm")
|
|
.arg("npm/no_npm_after_first_run/main1.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(
|
|
stderr,
|
|
"error: npm specifiers were requested; but --no-npm is specified\n at file:///"
|
|
);
|
|
assert!(stdout.is_empty());
|
|
assert!(!output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("npm/no_npm_after_first_run/main1.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(stderr, "Download");
|
|
assert_contains!(stdout, "[Function: chalk] createChalk");
|
|
assert!(output.status.success());
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(util::testdata_path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--no-npm")
|
|
.arg("npm/no_npm_after_first_run/main1.ts")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert_contains!(
|
|
stderr,
|
|
"error: npm specifiers were requested; but --no-npm is specified\n at file:///"
|
|
);
|
|
assert!(stdout.is_empty());
|
|
assert!(!output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn deno_run_cjs_module() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(deno_dir.path())
|
|
.arg("run")
|
|
.arg("--allow-read")
|
|
.arg("--allow-env")
|
|
.arg("--allow-write")
|
|
.arg("npm:mkdirp@1.0.4")
|
|
.arg("test_dir")
|
|
.env("NO_COLOR", "1")
|
|
.envs(env_vars_for_npm_tests())
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
assert!(output.status.success());
|
|
|
|
assert!(deno_dir.path().join("test_dir").exists());
|
|
}
|
|
|
|
#[test]
|
|
fn deno_run_bin_lockfile() {
|
|
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let temp_dir = context.temp_dir();
|
|
temp_dir.write("deno.json", "{}");
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --quiet npm:@denotest/bin/cli-esm this is a test")
|
|
.run();
|
|
output.assert_matches_file("npm/deno_run_esm.out");
|
|
assert!(temp_dir.path().join("deno.lock").exists());
|
|
}
|
|
|
|
#[test]
|
|
fn node_modules_dir_cache() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(deno_dir.path())
|
|
.arg("cache")
|
|
.arg("--node-modules-dir=auto")
|
|
.arg("--quiet")
|
|
.arg(util::testdata_path().join("npm/dual_cjs_esm/main.ts"))
|
|
.envs(env_vars_for_npm_tests())
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
assert!(output.status.success());
|
|
|
|
let node_modules = deno_dir.path().join("node_modules");
|
|
assert!(node_modules
|
|
.join(
|
|
".deno/@denotest+dual-cjs-esm@1.0.0/node_modules/@denotest/dual-cjs-esm"
|
|
)
|
|
.exists());
|
|
assert!(node_modules.join("@denotest/dual-cjs-esm").exists());
|
|
|
|
// now try deleting the folder with the package source in the npm cache dir
|
|
let package_global_cache_dir = deno_dir
|
|
.path()
|
|
.join("npm")
|
|
.join("localhost_4260")
|
|
.join("@denotest")
|
|
.join("dual-cjs-esm")
|
|
.join("1.0.0");
|
|
assert!(package_global_cache_dir.exists());
|
|
std::fs::remove_dir_all(&package_global_cache_dir).unwrap();
|
|
|
|
// run the output, and it shouldn't bother recreating the directory
|
|
// because it already has everything cached locally in the node_modules folder
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(deno_dir.path())
|
|
.arg("run")
|
|
.arg("--node-modules-dir=auto")
|
|
.arg("--quiet")
|
|
.arg("-A")
|
|
.arg(util::testdata_path().join("npm/dual_cjs_esm/main.ts"))
|
|
.envs(env_vars_for_npm_tests())
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
assert!(output.status.success());
|
|
|
|
// this won't exist, but actually the parent directory
|
|
// will because it still re-downloads the registry information
|
|
assert!(!package_global_cache_dir.exists());
|
|
}
|
|
|
|
#[test]
|
|
fn ensure_registry_files_local() {
|
|
// ensures the registry files all point at local tarballs
|
|
let registry_dir_path = util::tests_path().join("registry").join("npm");
|
|
for entry in std::fs::read_dir(®istry_dir_path).unwrap() {
|
|
let entry = entry.unwrap();
|
|
if entry.metadata().unwrap().is_dir() {
|
|
let registry_json_path = registry_dir_path
|
|
.join(entry.file_name())
|
|
.join("registry.json");
|
|
|
|
if registry_json_path.exists() {
|
|
let file_text = std::fs::read_to_string(®istry_json_path).unwrap();
|
|
if file_text.contains(&format!(
|
|
"https://registry.npmjs.org/{}/-/",
|
|
entry.file_name().to_string_lossy()
|
|
)) {
|
|
panic!(
|
|
"file {} contained a reference to the npm registry",
|
|
registry_json_path
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn lock_file_missing_top_level_package() {
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
let temp_dir = util::TempDir::new();
|
|
|
|
// write empty config file
|
|
temp_dir.write("deno.json", "{}");
|
|
|
|
// Lock file that is automatically picked up has been intentionally broken,
|
|
// by removing "cowsay" package from it. This test ensures that npm resolver
|
|
// snapshot can be successfully hydrated in such situation
|
|
let lock_file_content = r#"{
|
|
"version": "2",
|
|
"remote": {},
|
|
"npm": {
|
|
"specifiers": { "cowsay": "cowsay@1.5.0" },
|
|
"packages": {
|
|
"ansi-regex@3.0.1": {
|
|
"integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
|
|
"dependencies": {}
|
|
},
|
|
"ansi-regex@5.0.1": {
|
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
|
"dependencies": {}
|
|
},
|
|
"ansi-styles@4.3.0": {
|
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
"dependencies": { "color-convert": "color-convert@2.0.1" }
|
|
},
|
|
"camelcase@5.3.1": {
|
|
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
|
"dependencies": {}
|
|
},
|
|
"cliui@6.0.0": {
|
|
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
|
"dependencies": {
|
|
"string-width": "string-width@4.2.3",
|
|
"strip-ansi": "strip-ansi@6.0.1",
|
|
"wrap-ansi": "wrap-ansi@6.2.0"
|
|
}
|
|
},
|
|
"color-convert@2.0.1": {
|
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
"dependencies": { "color-name": "color-name@1.1.4" }
|
|
},
|
|
"color-name@1.1.4": {
|
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
|
"dependencies": {}
|
|
},
|
|
"decamelize@1.2.0": {
|
|
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
|
"dependencies": {}
|
|
},
|
|
"emoji-regex@8.0.0": {
|
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
|
"dependencies": {}
|
|
},
|
|
"find-up@4.1.0": {
|
|
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
|
"dependencies": {
|
|
"locate-path": "locate-path@5.0.0",
|
|
"path-exists": "path-exists@4.0.0"
|
|
}
|
|
},
|
|
"get-caller-file@2.0.5": {
|
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
|
"dependencies": {}
|
|
},
|
|
"get-stdin@8.0.0": {
|
|
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
|
|
"dependencies": {}
|
|
},
|
|
"is-fullwidth-code-point@2.0.0": {
|
|
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
|
|
"dependencies": {}
|
|
},
|
|
"is-fullwidth-code-point@3.0.0": {
|
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
|
"dependencies": {}
|
|
},
|
|
"locate-path@5.0.0": {
|
|
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
|
"dependencies": { "p-locate": "p-locate@4.1.0" }
|
|
},
|
|
"p-limit@2.3.0": {
|
|
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
|
"dependencies": { "p-try": "p-try@2.2.0" }
|
|
},
|
|
"p-locate@4.1.0": {
|
|
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
|
"dependencies": { "p-limit": "p-limit@2.3.0" }
|
|
},
|
|
"p-try@2.2.0": {
|
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
|
"dependencies": {}
|
|
},
|
|
"path-exists@4.0.0": {
|
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
|
"dependencies": {}
|
|
},
|
|
"require-directory@2.1.1": {
|
|
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
|
"dependencies": {}
|
|
},
|
|
"require-main-filename@2.0.0": {
|
|
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
|
"dependencies": {}
|
|
},
|
|
"set-blocking@2.0.0": {
|
|
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
|
"dependencies": {}
|
|
},
|
|
"string-width@2.1.1": {
|
|
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
|
"dependencies": {
|
|
"is-fullwidth-code-point": "is-fullwidth-code-point@2.0.0",
|
|
"strip-ansi": "strip-ansi@4.0.0"
|
|
}
|
|
},
|
|
"string-width@4.2.3": {
|
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
|
"dependencies": {
|
|
"emoji-regex": "emoji-regex@8.0.0",
|
|
"is-fullwidth-code-point": "is-fullwidth-code-point@3.0.0",
|
|
"strip-ansi": "strip-ansi@6.0.1"
|
|
}
|
|
},
|
|
"strip-ansi@4.0.0": {
|
|
"integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
|
|
"dependencies": { "ansi-regex": "ansi-regex@3.0.1" }
|
|
},
|
|
"strip-ansi@6.0.1": {
|
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
"dependencies": { "ansi-regex": "ansi-regex@5.0.1" }
|
|
},
|
|
"strip-final-newline@2.0.0": {
|
|
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
|
"dependencies": {}
|
|
},
|
|
"which-module@2.0.0": {
|
|
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
|
|
"dependencies": {}
|
|
},
|
|
"wrap-ansi@6.2.0": {
|
|
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
|
"dependencies": {
|
|
"ansi-styles": "ansi-styles@4.3.0",
|
|
"string-width": "string-width@4.2.3",
|
|
"strip-ansi": "strip-ansi@6.0.1"
|
|
}
|
|
},
|
|
"y18n@4.0.3": {
|
|
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
|
"dependencies": {}
|
|
},
|
|
"yargs-parser@18.1.3": {
|
|
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
|
"dependencies": {
|
|
"camelcase": "camelcase@5.3.1",
|
|
"decamelize": "decamelize@1.2.0"
|
|
}
|
|
},
|
|
"yargs@15.4.1": {
|
|
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
|
"dependencies": {
|
|
"cliui": "cliui@6.0.0",
|
|
"decamelize": "decamelize@1.2.0",
|
|
"find-up": "find-up@4.1.0",
|
|
"get-caller-file": "get-caller-file@2.0.5",
|
|
"require-directory": "require-directory@2.1.1",
|
|
"require-main-filename": "require-main-filename@2.0.0",
|
|
"set-blocking": "set-blocking@2.0.0",
|
|
"string-width": "string-width@4.2.3",
|
|
"which-module": "which-module@2.0.0",
|
|
"y18n": "y18n@4.0.3",
|
|
"yargs-parser": "yargs-parser@18.1.3"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"#;
|
|
temp_dir.write("deno.lock", lock_file_content);
|
|
let main_contents = r#"
|
|
import cowsay from "npm:cowsay";
|
|
console.log(cowsay);
|
|
"#;
|
|
temp_dir.write("main.ts", main_contents);
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(temp_dir.path())
|
|
.arg("run")
|
|
.arg("--quiet")
|
|
.arg("--lock")
|
|
.arg("deno.lock")
|
|
.arg("-A")
|
|
.arg("main.ts")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
assert!(!output.status.success());
|
|
|
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
|
assert_eq!(
|
|
stderr,
|
|
concat!(
|
|
"error: failed reading lockfile 'deno.lock'\n",
|
|
"\n",
|
|
"Caused by:\n",
|
|
" 0: The lockfile is corrupt. Remove the lockfile to regenerate it.\n",
|
|
" 1: Could not find 'cowsay@1.5.0' in the list of packages.\n"
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn lock_file_lock_write() {
|
|
// https://github.com/denoland/deno/issues/16666
|
|
let _server = http_server();
|
|
|
|
let deno_dir = util::new_deno_dir();
|
|
let temp_dir = util::TempDir::new();
|
|
|
|
temp_dir.write("deno.json", "{}");
|
|
let lock_file_content = r#"{
|
|
"version": "4",
|
|
"specifiers": {
|
|
"npm:cowsay@1.5.0": "1.5.0"
|
|
},
|
|
"npm": {
|
|
"ansi-regex@3.0.1": {
|
|
"integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw=="
|
|
},
|
|
"ansi-regex@5.0.1": {
|
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
|
},
|
|
"ansi-styles@4.3.0": {
|
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
"dependencies": [
|
|
"color-convert"
|
|
]
|
|
},
|
|
"camelcase@5.3.1": {
|
|
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
|
},
|
|
"cliui@6.0.0": {
|
|
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
|
"dependencies": [
|
|
"string-width@4.2.3",
|
|
"strip-ansi@6.0.1",
|
|
"wrap-ansi"
|
|
]
|
|
},
|
|
"color-convert@2.0.1": {
|
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
"dependencies": [
|
|
"color-name"
|
|
]
|
|
},
|
|
"color-name@1.1.4": {
|
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
|
},
|
|
"cowsay@1.5.0": {
|
|
"integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==",
|
|
"dependencies": [
|
|
"get-stdin",
|
|
"string-width@2.1.1",
|
|
"strip-final-newline",
|
|
"yargs"
|
|
]
|
|
},
|
|
"decamelize@1.2.0": {
|
|
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
|
|
},
|
|
"emoji-regex@8.0.0": {
|
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
|
},
|
|
"find-up@4.1.0": {
|
|
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
|
"dependencies": [
|
|
"locate-path",
|
|
"path-exists"
|
|
]
|
|
},
|
|
"get-caller-file@2.0.5": {
|
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
|
},
|
|
"get-stdin@8.0.0": {
|
|
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg=="
|
|
},
|
|
"is-fullwidth-code-point@2.0.0": {
|
|
"integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w=="
|
|
},
|
|
"is-fullwidth-code-point@3.0.0": {
|
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
|
},
|
|
"locate-path@5.0.0": {
|
|
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
|
"dependencies": [
|
|
"p-locate"
|
|
]
|
|
},
|
|
"p-limit@2.3.0": {
|
|
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
|
"dependencies": [
|
|
"p-try"
|
|
]
|
|
},
|
|
"p-locate@4.1.0": {
|
|
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
|
"dependencies": [
|
|
"p-limit"
|
|
]
|
|
},
|
|
"p-try@2.2.0": {
|
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
|
},
|
|
"path-exists@4.0.0": {
|
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
|
},
|
|
"require-directory@2.1.1": {
|
|
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
|
|
},
|
|
"require-main-filename@2.0.0": {
|
|
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
|
},
|
|
"set-blocking@2.0.0": {
|
|
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
|
|
},
|
|
"string-width@2.1.1": {
|
|
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
|
"dependencies": [
|
|
"is-fullwidth-code-point@2.0.0",
|
|
"strip-ansi@4.0.0"
|
|
]
|
|
},
|
|
"string-width@4.2.3": {
|
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
|
"dependencies": [
|
|
"emoji-regex",
|
|
"is-fullwidth-code-point@3.0.0",
|
|
"strip-ansi@6.0.1"
|
|
]
|
|
},
|
|
"strip-ansi@4.0.0": {
|
|
"integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
|
|
"dependencies": [
|
|
"ansi-regex@3.0.1"
|
|
]
|
|
},
|
|
"strip-ansi@6.0.1": {
|
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
|
"dependencies": [
|
|
"ansi-regex@5.0.1"
|
|
]
|
|
},
|
|
"strip-final-newline@2.0.0": {
|
|
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
|
|
},
|
|
"which-module@2.0.0": {
|
|
"integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q=="
|
|
},
|
|
"wrap-ansi@6.2.0": {
|
|
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
|
"dependencies": [
|
|
"ansi-styles",
|
|
"string-width@4.2.3",
|
|
"strip-ansi@6.0.1"
|
|
]
|
|
},
|
|
"y18n@4.0.3": {
|
|
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
|
|
},
|
|
"yargs-parser@18.1.3": {
|
|
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
|
"dependencies": [
|
|
"camelcase",
|
|
"decamelize"
|
|
]
|
|
},
|
|
"yargs@15.4.1": {
|
|
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
|
"dependencies": [
|
|
"cliui",
|
|
"decamelize",
|
|
"find-up",
|
|
"get-caller-file",
|
|
"require-directory",
|
|
"require-main-filename",
|
|
"set-blocking",
|
|
"string-width@4.2.3",
|
|
"which-module",
|
|
"y18n",
|
|
"yargs-parser"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
"#;
|
|
temp_dir.write("deno.lock", lock_file_content);
|
|
|
|
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
|
.current_dir(temp_dir.path())
|
|
.arg("cache")
|
|
.arg("--quiet")
|
|
.arg("npm:cowsay@1.5.0")
|
|
.envs(env_vars_for_npm_tests())
|
|
.piped_output()
|
|
.spawn()
|
|
.unwrap();
|
|
let output = deno.wait_with_output().unwrap();
|
|
assert!(output.status.success());
|
|
assert_eq!(output.status.code(), Some(0));
|
|
|
|
let stdout = String::from_utf8(output.stdout).unwrap();
|
|
assert!(stdout.is_empty());
|
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
|
assert!(stderr.is_empty());
|
|
assert_eq!(
|
|
std::fs::read_to_string(temp_dir.path().join("deno.lock")).unwrap(),
|
|
lock_file_content,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn auto_discover_lock_file() {
|
|
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
|
|
let temp_dir = context.temp_dir();
|
|
|
|
// write empty config file
|
|
temp_dir.write("deno.json", "{}");
|
|
|
|
// write a lock file with borked integrity
|
|
let lock_file_content = r#"{
|
|
"version": "4",
|
|
"specifiers": {
|
|
"npm:@denotest/bin": "1.0.0"
|
|
},
|
|
"npm": {
|
|
"@denotest/bin@1.0.0": {
|
|
"integrity": "sha512-foobar"
|
|
}
|
|
}
|
|
}"#;
|
|
temp_dir.write("deno.lock", lock_file_content);
|
|
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A npm:@denotest/bin/cli-esm test")
|
|
.run();
|
|
output
|
|
.assert_matches_text(
|
|
r#"Download http://localhost:4260/@denotest%2fbin
|
|
error: Integrity check failed for package: "npm:@denotest/bin@1.0.0". Unable to verify that the package
|
|
is the same as when the lockfile was generated.
|
|
|
|
Actual: sha512-[WILDCARD]
|
|
Expected: sha512-foobar
|
|
|
|
This could be caused by:
|
|
* the lock file may be corrupt
|
|
* the source itself may be corrupt
|
|
|
|
Investigate the lockfile; delete it to regenerate the lockfile at "[WILDCARD]deno.lock".
|
|
"#)
|
|
.assert_exit_code(10);
|
|
}
|
|
|
|
#[test]
|
|
fn peer_deps_with_copied_folders_and_lockfile() {
|
|
let context = TestContextBuilder::for_npm()
|
|
.use_copy_temp_dir("npm/peer_deps_with_copied_folders")
|
|
.cwd("npm/peer_deps_with_copied_folders")
|
|
.build();
|
|
|
|
let deno_dir = context.deno_dir();
|
|
let temp_dir = context.temp_dir();
|
|
let temp_dir_sub_path =
|
|
temp_dir.path().join("npm/peer_deps_with_copied_folders");
|
|
|
|
// write empty config file
|
|
temp_dir.write("npm/peer_deps_with_copied_folders/deno.json", "{}");
|
|
|
|
let output = context.new_command().args("run -A main.ts").run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_file("npm/peer_deps_with_copied_folders/main.out");
|
|
|
|
assert!(temp_dir_sub_path.join("deno.lock").exists());
|
|
let grandchild_path = deno_dir
|
|
.path()
|
|
.join("npm")
|
|
.join("localhost_4260")
|
|
.join("@denotest")
|
|
.join("peer-dep-test-grandchild");
|
|
assert!(grandchild_path.join("1.0.0").exists());
|
|
assert!(grandchild_path.join("1.0.0_1").exists()); // copy folder, which is hardlinked
|
|
|
|
// run again
|
|
let output = context.new_command().args("run -A main.ts").run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_text("1\n2\n");
|
|
|
|
// run with reload
|
|
let output = context.new_command().args("run -A --reload main.ts").run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_file("npm/peer_deps_with_copied_folders/main.out");
|
|
|
|
// now run with local node modules
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --node-modules-dir=auto main.ts")
|
|
.run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_file(
|
|
"npm/peer_deps_with_copied_folders/main_node_modules.out",
|
|
);
|
|
|
|
let deno_folder = temp_dir_sub_path.join("node_modules").join(".deno");
|
|
assert!(deno_folder
|
|
.join("@denotest+peer-dep-test-grandchild@1.0.0")
|
|
.exists());
|
|
assert!(deno_folder
|
|
.join("@denotest+peer-dep-test-grandchild@1.0.0_1")
|
|
.exists()); // copy folder
|
|
|
|
// now again run with local node modules
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --node-modules-dir=auto main.ts")
|
|
.run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_text("1\n2\n");
|
|
|
|
// now ensure it works with reloading
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --reload --node-modules-dir=auto main.ts")
|
|
.run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_file(
|
|
"npm/peer_deps_with_copied_folders/main_node_modules_reload.out",
|
|
);
|
|
|
|
// now ensure it works with reloading and no lockfile
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --reload --node-modules-dir=auto --no-lock main.ts")
|
|
.run();
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_file(
|
|
"npm/peer_deps_with_copied_folders/main_node_modules_reload.out",
|
|
);
|
|
}
|
|
|
|
// TODO(2.0): this should be rewritten to a spec test and first run `deno install`
|
|
// itest!(node_modules_import_run {
|
|
// args: "run --quiet main.ts",
|
|
// output: "npm/node_modules_import/main.out",
|
|
// http_server: true,
|
|
// copy_temp_dir: Some("npm/node_modules_import/"),
|
|
// cwd: Some("npm/node_modules_import/"),
|
|
// envs: env_vars_for_npm_tests(),
|
|
// exit_code: 0,
|
|
// });
|
|
|
|
// TODO(2.0): this should be rewritten to a spec test and first run `deno install`
|
|
// itest!(node_modules_import_check {
|
|
// args: "check --quiet main.ts",
|
|
// output: "npm/node_modules_import/main_check.out",
|
|
// envs: env_vars_for_npm_tests(),
|
|
// http_server: true,
|
|
// cwd: Some("npm/node_modules_import/"),
|
|
// copy_temp_dir: Some("npm/node_modules_import/"),
|
|
// exit_code: 1,
|
|
// });
|
|
|
|
// TODO(2.0): this should be rewritten to a spec test and first run `deno install`
|
|
#[test]
|
|
#[ignore]
|
|
fn reload_info_not_found_cache_but_exists_remote() {
|
|
fn remove_version(registry_json: &mut Value, version: &str) {
|
|
registry_json
|
|
.as_object_mut()
|
|
.unwrap()
|
|
.get_mut("versions")
|
|
.unwrap()
|
|
.as_object_mut()
|
|
.unwrap()
|
|
.remove(version);
|
|
}
|
|
|
|
fn remove_version_for_package(
|
|
deno_dir: &util::TempDir,
|
|
package: &str,
|
|
version: &str,
|
|
) {
|
|
let registry_json_path =
|
|
format!("npm/localhost_4260/{}/registry.json", package);
|
|
let mut registry_json: Value =
|
|
serde_json::from_str(&deno_dir.read_to_string(®istry_json_path))
|
|
.unwrap();
|
|
remove_version(&mut registry_json, version);
|
|
// for the purpose of this test, just remove the dist-tag as it might contain this version
|
|
registry_json
|
|
.as_object_mut()
|
|
.unwrap()
|
|
.get_mut("dist-tags")
|
|
.unwrap()
|
|
.as_object_mut()
|
|
.unwrap()
|
|
.remove("latest");
|
|
deno_dir.write(
|
|
®istry_json_path,
|
|
serde_json::to_string(®istry_json).unwrap(),
|
|
);
|
|
}
|
|
|
|
// This tests that when a local machine doesn't have a version
|
|
// specified in a dependency that exists in the npm registry
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let deno_dir = test_context.deno_dir();
|
|
let temp_dir = test_context.temp_dir();
|
|
temp_dir.write(
|
|
"main.ts",
|
|
"import 'npm:@denotest/esm-import-cjs-default@1.0.0';",
|
|
);
|
|
|
|
// cache successfully to the deno_dir
|
|
let output = test_context
|
|
.new_command()
|
|
.args("cache main.ts npm:@denotest/esm-basic@1.0.0")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-basic\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"Download http://localhost:4260/@denotestcjs-default-export/1.0.0.tgz\n",
|
|
"Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz\n",
|
|
"Download http://localhost:4260/@denotest/esm-import-cjs-default/1.0.0.tgz\n",
|
|
"[UNORDERED_END]\n",
|
|
));
|
|
|
|
// test in dependency
|
|
{
|
|
// modify the package information in the cache to remove the latest version
|
|
remove_version_for_package(
|
|
deno_dir,
|
|
"@denotest/cjs-default-export",
|
|
"1.0.0",
|
|
);
|
|
|
|
// should error when `--cache-only` is used now because the version is not in the cache
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --cached-only main.ts")
|
|
.run();
|
|
output.assert_exit_code(1);
|
|
output.assert_matches_text("error: Could not find npm package '@denotest/cjs-default-export' matching '^1.0.0'.\n");
|
|
|
|
// now try running without it, it should download the package now
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"[UNORDERED_END]\n",
|
|
"Node esm importing node cjs\n[WILDCARD]",
|
|
));
|
|
output.assert_exit_code(0);
|
|
}
|
|
|
|
// test in npm specifier
|
|
{
|
|
// now remove the information for the top level package
|
|
remove_version_for_package(
|
|
deno_dir,
|
|
"@denotest/esm-import-cjs-default",
|
|
"1.0.0",
|
|
);
|
|
|
|
// should error for --cached-only
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --cached-only main.ts")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'.\n",
|
|
" at file:///[WILDCARD]/main.ts:1:8\n",
|
|
));
|
|
output.assert_exit_code(1);
|
|
|
|
// now try running, it should work
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"[UNORDERED_END]\n",
|
|
"Node esm importing node cjs\n[WILDCARD]",
|
|
));
|
|
output.assert_exit_code(0);
|
|
}
|
|
|
|
// test matched specifier in package.json
|
|
{
|
|
// write out a package.json and a new main.ts with a bare specifier
|
|
temp_dir.write("main.ts", "import '@denotest/esm-import-cjs-default';");
|
|
temp_dir.write(
|
|
"package.json",
|
|
r#"{ "dependencies": { "@denotest/esm-import-cjs-default": "1.0.0" }}"#,
|
|
);
|
|
|
|
// remove the top level package information again
|
|
remove_version_for_package(
|
|
deno_dir,
|
|
"@denotest/esm-import-cjs-default",
|
|
"1.0.0",
|
|
);
|
|
|
|
// should error for --cached-only
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --cached-only main.ts")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"error: Could not find npm package '@denotest/esm-import-cjs-default' matching '1.0.0'.\n",
|
|
" at file:///[WILDCARD]/main.ts:1:8\n",
|
|
));
|
|
output.assert_exit_code(1);
|
|
|
|
// now try running, it should work
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"[UNORDERED_END]\n",
|
|
"[UNORDERED_START]\n",
|
|
"Initialize @denotest/cjs-default-export@1.0.0\n",
|
|
"Initialize @denotest/esm-import-cjs-default@1.0.0\n",
|
|
"[UNORDERED_END]\n",
|
|
"Node esm importing node cjs\n[WILDCARD]",
|
|
));
|
|
output.assert_exit_code(0);
|
|
}
|
|
|
|
// temp other dependency in package.json
|
|
{
|
|
// write out a package.json that has another dependency
|
|
temp_dir.write(
|
|
"package.json",
|
|
r#"{ "dependencies": { "@denotest/esm-import-cjs-default": "1.0.0", "@denotest/esm-basic": "1.0.0" }}"#,
|
|
);
|
|
|
|
// remove the dependency's version
|
|
remove_version_for_package(deno_dir, "@denotest/esm-basic", "1.0.0");
|
|
|
|
// should error for --cached-only
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --cached-only main.ts")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"error: Could not find npm package '@denotest/esm-basic' matching '1.0.0'.\n",
|
|
));
|
|
output.assert_exit_code(1);
|
|
|
|
// now try running, it should work and only initialize the new package
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-basic\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"[UNORDERED_END]\n",
|
|
"Initialize @denotest/esm-basic@1.0.0\n",
|
|
"Node esm importing node cjs\n[WILDCARD]",
|
|
));
|
|
output.assert_exit_code(0);
|
|
}
|
|
|
|
// now try using a lockfile
|
|
{
|
|
// create it
|
|
temp_dir.write("deno.json", r#"{}"#);
|
|
test_context
|
|
.new_command()
|
|
.args("install --entrypoint main.ts")
|
|
.run();
|
|
assert!(temp_dir.path().join("deno.lock").exists());
|
|
|
|
// remove a version found in the lockfile
|
|
remove_version_for_package(deno_dir, "@denotest/esm-basic", "1.0.0");
|
|
|
|
// should error for --cached-only
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --cached-only main.ts")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"error: failed reading lockfile '[WILDCARD]deno.lock'\n",
|
|
"\n",
|
|
"Caused by:\n",
|
|
" 0: Could not find '@denotest/esm-basic@1.0.0' specified in the lockfile.\n",
|
|
" 1: Could not find version '1.0.0' for npm package '@denotest/esm-basic'.\n",
|
|
));
|
|
output.assert_exit_code(1);
|
|
|
|
// now try running, it should work and only initialize the new package
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"[UNORDERED_START]\n",
|
|
"Download http://localhost:4260/@denotest%2fcjs-default-export\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-basic\n",
|
|
"Download http://localhost:4260/@denotest%2fesm-import-cjs-default\n",
|
|
"[UNORDERED_END]\n",
|
|
"Node esm importing node cjs\n[WILDCARD]",
|
|
));
|
|
output.assert_exit_code(0);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn binary_package_with_optional_dependencies() {
|
|
let context = TestContextBuilder::for_npm()
|
|
.use_copy_temp_dir("npm/binary_package")
|
|
.cwd("npm/binary_package")
|
|
.build();
|
|
|
|
let temp_dir = context.temp_dir();
|
|
let temp_dir_path = temp_dir.path();
|
|
let project_path = temp_dir_path.join("npm/binary_package");
|
|
|
|
// write empty config file so a lockfile gets created
|
|
temp_dir.write("npm/binary_package/deno.json", "{}");
|
|
|
|
// run it twice, with the first time creating the lockfile and the second using it
|
|
for i in 0..2 {
|
|
if i == 1 {
|
|
assert!(project_path.join("deno.lock").exists());
|
|
}
|
|
|
|
let output = context
|
|
.new_command()
|
|
.args("run -A --node-modules-dir=auto main.js")
|
|
.run();
|
|
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_text(
|
|
"[WILDCARD]Hello from binary package on windows[WILDCARD]",
|
|
);
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-windows@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-linux@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-mac@1.0.0")
|
|
.exists());
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-windows")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-linux")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-mac")
|
|
.exists());
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_text(
|
|
"[WILDCARD]Hello from binary package on mac[WILDCARD]",
|
|
);
|
|
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-windows@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-linux@1.0.0")
|
|
.exists());
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-mac@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-windows")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-linux")
|
|
.exists());
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-mac")
|
|
.exists());
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
output.assert_exit_code(0);
|
|
output.assert_matches_text(
|
|
"[WILDCARD]Hello from binary package on linux[WILDCARD]",
|
|
);
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-windows@1.0.0")
|
|
.exists());
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-linux@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package-mac@1.0.0")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-windows")
|
|
.exists());
|
|
assert!(project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-linux")
|
|
.exists());
|
|
assert!(!project_path
|
|
.join("node_modules/.deno/@denotest+binary-package@1.0.0/node_modules/@denotest/binary-package-mac")
|
|
.exists());
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn node_modules_dir_config_file() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let temp_dir = test_context.temp_dir();
|
|
let node_modules_dir = temp_dir.path().join("node_modules");
|
|
let rm_node_modules = || std::fs::remove_dir_all(&node_modules_dir).unwrap();
|
|
|
|
temp_dir.write("deno.json", r#"{ "nodeModulesDir": "auto" }"#);
|
|
temp_dir.write("main.ts", "import 'npm:@denotest/esm-basic';");
|
|
|
|
let deno_cache_cmd = test_context.new_command().args("cache --quiet main.ts");
|
|
deno_cache_cmd.run();
|
|
assert!(node_modules_dir.exists());
|
|
|
|
// now try adding a vendor flag, it should exist
|
|
rm_node_modules();
|
|
temp_dir.write("deno.json", r#"{ "vendor": true }"#);
|
|
deno_cache_cmd.run();
|
|
assert!(node_modules_dir.exists());
|
|
|
|
rm_node_modules();
|
|
temp_dir.write("deno.json", r#"{ "nodeModulesDir": "none" }"#);
|
|
|
|
deno_cache_cmd.run();
|
|
assert!(!node_modules_dir.exists());
|
|
|
|
temp_dir.write("package.json", r#"{}"#);
|
|
deno_cache_cmd.run();
|
|
assert!(!node_modules_dir.exists());
|
|
|
|
test_context
|
|
.new_command()
|
|
.args("cache --quiet --node-modules-dir=auto main.ts")
|
|
.run();
|
|
assert!(node_modules_dir.exists());
|
|
|
|
// should override the `--vendor` flag
|
|
rm_node_modules();
|
|
test_context
|
|
.new_command()
|
|
.args("cache --quiet --node-modules-dir=none --vendor main.ts")
|
|
.run();
|
|
assert!(!node_modules_dir.exists());
|
|
}
|
|
|
|
#[test]
|
|
fn top_level_install_package_json_explicit_opt_in() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let temp_dir = test_context.temp_dir();
|
|
let node_modules_dir = temp_dir.path().join("node_modules");
|
|
let rm_created_files = || {
|
|
std::fs::remove_dir_all(&node_modules_dir).unwrap();
|
|
std::fs::remove_file(temp_dir.path().join("deno.lock")).unwrap();
|
|
};
|
|
|
|
// when the node_modules_dir is explicitly opted into, we should always
|
|
// ensure a top level package.json install occurs
|
|
temp_dir.write("deno.json", "{ \"nodeModulesDir\": \"auto\" }");
|
|
temp_dir.write(
|
|
"package.json",
|
|
"{ \"dependencies\": { \"@denotest/esm-basic\": \"1.0\" }}",
|
|
);
|
|
|
|
temp_dir.write("main.ts", "console.log(5);");
|
|
let output = test_context.new_command().args("cache main.ts").run();
|
|
output.assert_matches_text(concat!(
|
|
"Download http://localhost:4260/@denotest%2fesm-basic\n",
|
|
"Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz\n",
|
|
"Initialize @denotest/esm-basic@1.0.0\n",
|
|
));
|
|
|
|
rm_created_files();
|
|
let output = test_context
|
|
.new_command()
|
|
.args_vec(["eval", "console.log(5)"])
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"Initialize @denotest/esm-basic@1.0.0\n",
|
|
"5\n"
|
|
));
|
|
|
|
rm_created_files();
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run -")
|
|
.stdin_text("console.log(5)")
|
|
.run();
|
|
output.assert_matches_text(concat!(
|
|
"Initialize @denotest/esm-basic@1.0.0\n",
|
|
"5\n"
|
|
));
|
|
|
|
// now ensure this is cached in the lsp
|
|
rm_created_files();
|
|
let mut client = test_context.new_lsp_command().build();
|
|
client.initialize_default();
|
|
let file_uri = temp_dir.url().join("file.ts").unwrap();
|
|
client.did_open(json!({
|
|
"textDocument": {
|
|
"uri": file_uri,
|
|
"languageId": "typescript",
|
|
"version": 1,
|
|
"text": "",
|
|
}
|
|
}));
|
|
client.write_request(
|
|
"workspace/executeCommand",
|
|
json!({
|
|
"command": "deno.cache",
|
|
"arguments": [[], file_uri],
|
|
}),
|
|
);
|
|
|
|
assert!(node_modules_dir.join("@denotest").exists());
|
|
}
|
|
|
|
#[test]
|
|
fn byonm_cjs_esm_packages() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
|
|
test_context.run_npm("init -y");
|
|
test_context.run_npm("install @denotest/esm-basic @denotest/cjs-default-export @denotest/dual-cjs-esm chalk@4 chai@4.3");
|
|
|
|
dir.write(
|
|
"main.ts",
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(2);
|
|
console.log(getValue());
|
|
|
|
import cjsDefault from "@denotest/cjs-default-export";
|
|
console.log(cjsDefault.default());
|
|
console.log(cjsDefault.named());
|
|
|
|
import { getKind } from "@denotest/dual-cjs-esm";
|
|
console.log(getKind());
|
|
|
|
|
|
"#,
|
|
);
|
|
let output = test_context.new_command().args("run --check main.ts").run();
|
|
output
|
|
.assert_matches_text("Check file:///[WILDCARD]/main.ts\n2\n1\n2\nesm\n");
|
|
|
|
// should not have created the .deno directory
|
|
assert!(!dir.path().join("node_modules/.deno").exists());
|
|
|
|
// try chai
|
|
dir.write(
|
|
"chai.ts",
|
|
r#"import { expect } from "chai";
|
|
|
|
const timeout = setTimeout(() => {}, 0);
|
|
expect(timeout).to.be.a("number");
|
|
clearTimeout(timeout);"#,
|
|
);
|
|
test_context.new_command().args("run chai.ts").run();
|
|
|
|
// try chalk cjs
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'chalk'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text("chalk cjs loads\n");
|
|
|
|
// try using an npm specifier for chalk that matches the version we installed
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'npm:chalk@4'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text("chalk cjs loads\n");
|
|
|
|
// try with one that doesn't match the package.json
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'npm:chalk@5'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text(
|
|
r#"error: Could not find a matching package for 'npm:chalk@5' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `"nodeModulesDir": "auto"` in your deno.json file.
|
|
at file:///[WILDCARD]chalk.ts:1:19
|
|
"#);
|
|
output.assert_exit_code(1);
|
|
}
|
|
|
|
#[test]
|
|
fn future_byonm_cjs_esm_packages() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
|
|
test_context.run_npm("init -y");
|
|
test_context.run_npm("install @denotest/esm-basic @denotest/cjs-default-export @denotest/dual-cjs-esm chalk@4 chai@4.3");
|
|
|
|
dir.write(
|
|
"main.ts",
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(2);
|
|
console.log(getValue());
|
|
|
|
import cjsDefault from "@denotest/cjs-default-export";
|
|
console.log(cjsDefault.default());
|
|
console.log(cjsDefault.named());
|
|
|
|
import { getKind } from "@denotest/dual-cjs-esm";
|
|
console.log(getKind());
|
|
|
|
|
|
"#,
|
|
);
|
|
let output = test_context.new_command().args("run --check main.ts").run();
|
|
output
|
|
.assert_matches_text("Check file:///[WILDCARD]/main.ts\n2\n1\n2\nesm\n");
|
|
|
|
// should not have created the .deno directory
|
|
assert!(!dir.path().join("node_modules/.deno").exists());
|
|
|
|
// try chai
|
|
dir.write(
|
|
"chai.ts",
|
|
r#"import { expect } from "chai";
|
|
|
|
const timeout = setTimeout(() => {}, 0);
|
|
expect(timeout).to.be.a("number");
|
|
clearTimeout(timeout);"#,
|
|
);
|
|
test_context.new_command().args("run chai.ts").run();
|
|
|
|
// try chalk cjs
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'chalk'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text("chalk cjs loads\n");
|
|
|
|
// try using an npm specifier for chalk that matches the version we installed
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'npm:chalk@4'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text("chalk cjs loads\n");
|
|
|
|
// try with one that doesn't match the package.json
|
|
dir.write(
|
|
"chalk.ts",
|
|
"import chalk from 'npm:chalk@5'; console.log(chalk.green('chalk cjs loads'));",
|
|
);
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read chalk.ts")
|
|
.run();
|
|
output.assert_matches_text(
|
|
r#"error: Could not find a matching package for 'npm:chalk@5' in the node_modules directory. Ensure you have all your JSR and npm dependencies listed in your deno.json or package.json, then run `deno install`. Alternatively, turn on auto-install by specifying `"nodeModulesDir": "auto"` in your deno.json file.
|
|
at file:///[WILDCARD]chalk.ts:1:19
|
|
"#);
|
|
output.assert_exit_code(1);
|
|
}
|
|
|
|
#[test]
|
|
fn node_modules_dir_manual_import_map() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write(
|
|
"deno.json",
|
|
r#"{
|
|
"nodeModulesDir": "manual",
|
|
"imports": {
|
|
"basic": "npm:@denotest/esm-basic"
|
|
}
|
|
}"#,
|
|
);
|
|
dir.write(
|
|
"package.json",
|
|
r#"{
|
|
"name": "my-project",
|
|
"version": "1.0.0",
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@denotest/esm-basic": "^1.0"
|
|
}
|
|
}"#,
|
|
);
|
|
test_context.run_npm("install");
|
|
|
|
dir.write(
|
|
"main.ts",
|
|
r#"
|
|
// import map should resolve
|
|
import { getValue } from "basic";
|
|
// and resolving via node resolution
|
|
import { setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(5);
|
|
console.log(getValue());
|
|
"#,
|
|
);
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text("5\n");
|
|
let output = test_context.new_command().args("check main.ts").run();
|
|
output.assert_matches_text("Check file:///[WILDCARD]/main.ts\n");
|
|
}
|
|
|
|
#[test]
|
|
fn byonm_package_specifier_not_installed_and_invalid_subpath() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.path().join("package.json").write_json(&json!({
|
|
"dependencies": {
|
|
"chalk": "4",
|
|
"@denotest/conditional-exports-strict": "1"
|
|
}
|
|
}));
|
|
dir.write(
|
|
"main.ts",
|
|
"import chalk from 'chalk'; console.log(chalk.green('hi'));",
|
|
);
|
|
|
|
// no npm install has been run, so this should give an informative error
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(
|
|
r#"error: Could not resolve "chalk", but found it in a package.json. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?
|
|
at file:///[WILDCARD]/main.ts:1:19
|
|
"#,
|
|
);
|
|
output.assert_exit_code(1);
|
|
|
|
// now test for an invalid sub path after doing an npm install
|
|
dir.write(
|
|
"main.ts",
|
|
"import '@denotest/conditional-exports-strict/test';",
|
|
);
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text(
|
|
r#"error: [ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './test' is not defined by "exports" in '[WILDCARD]' imported from '[WILDCARD]main.ts'
|
|
at file:///[WILDCARD]/main.ts:1:8
|
|
"#,
|
|
);
|
|
output.assert_exit_code(1);
|
|
}
|
|
|
|
#[test]
|
|
fn byonm_npm_workspaces() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write("deno.json", r#"{ "unstable": [ "byonm" ] }"#);
|
|
|
|
dir.write(
|
|
"package.json",
|
|
r#"{
|
|
"name": "my-workspace",
|
|
"workspaces": [
|
|
"project-a",
|
|
"project-b"
|
|
]
|
|
}
|
|
"#,
|
|
);
|
|
|
|
let project_a_dir = dir.path().join("project-a");
|
|
project_a_dir.create_dir_all();
|
|
project_a_dir.join("package.json").write_json(&json!({
|
|
"name": "project-a",
|
|
"version": "1.0.0",
|
|
"main": "./index.js",
|
|
"type": "module",
|
|
"dependencies": {
|
|
"chai": "^4.2",
|
|
"project-b": "^1"
|
|
}
|
|
}));
|
|
project_a_dir.join("index.js").write(
|
|
r#"
|
|
import { expect } from "chai";
|
|
|
|
const timeout = setTimeout(() => {}, 0);
|
|
expect(timeout).to.be.a("number");
|
|
clearTimeout(timeout);
|
|
|
|
export function add(a, b) {
|
|
return a + b;
|
|
}
|
|
"#,
|
|
);
|
|
project_a_dir
|
|
.join("index.d.ts")
|
|
.write("export function add(a: number, b: number): number;");
|
|
|
|
let project_b_dir = dir.path().join("project-b");
|
|
project_b_dir.create_dir_all();
|
|
project_b_dir.join("package.json").write_json(&json!({
|
|
"name": "project-b",
|
|
"version": "1.0.0",
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@denotest/esm-basic": "^1.0",
|
|
}
|
|
}));
|
|
project_b_dir.join("main.ts").write(
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(5);
|
|
console.log(getValue());
|
|
|
|
import { add } from "project-a";
|
|
console.log(add(1, 2));
|
|
"#,
|
|
);
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run ./project-b/main.ts")
|
|
.run();
|
|
output.assert_matches_text("5\n3\n");
|
|
let output = test_context
|
|
.new_command()
|
|
.args("check ./project-b/main.ts")
|
|
.run();
|
|
output.assert_matches_text("Check file:///[WILDCARD]/project-b/main.ts\n");
|
|
|
|
// Now a file in the main directory should just be able to
|
|
// import it via node resolution even though a package.json
|
|
// doesn't exist here
|
|
dir.write(
|
|
"main.ts",
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(7);
|
|
console.log(getValue());
|
|
"#,
|
|
);
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text("7\n");
|
|
let output = test_context.new_command().args("check main.ts").run();
|
|
output.assert_matches_text("Check file:///[WILDCARD]/main.ts\n");
|
|
}
|
|
|
|
#[test]
|
|
fn future_byonm_npm_workspaces() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
|
|
dir.write(
|
|
"package.json",
|
|
r#"{
|
|
"name": "my-workspace",
|
|
"workspaces": [
|
|
"project-a",
|
|
"project-b"
|
|
]
|
|
}
|
|
"#,
|
|
);
|
|
|
|
let project_a_dir = dir.path().join("project-a");
|
|
project_a_dir.create_dir_all();
|
|
project_a_dir.join("package.json").write_json(&json!({
|
|
"name": "project-a",
|
|
"version": "1.0.0",
|
|
"main": "./index.js",
|
|
"type": "module",
|
|
"dependencies": {
|
|
"chai": "^4.2",
|
|
"project-b": "^1"
|
|
}
|
|
}));
|
|
project_a_dir.join("index.js").write(
|
|
r#"
|
|
import { expect } from "chai";
|
|
|
|
const timeout = setTimeout(() => {}, 0);
|
|
expect(timeout).to.be.a("number");
|
|
clearTimeout(timeout);
|
|
|
|
export function add(a, b) {
|
|
return a + b;
|
|
}
|
|
"#,
|
|
);
|
|
project_a_dir
|
|
.join("index.d.ts")
|
|
.write("export function add(a: number, b: number): number;");
|
|
|
|
let project_b_dir = dir.path().join("project-b");
|
|
project_b_dir.create_dir_all();
|
|
project_b_dir.join("package.json").write_json(&json!({
|
|
"name": "project-b",
|
|
"version": "1.0.0",
|
|
"type": "module",
|
|
"dependencies": {
|
|
"@denotest/esm-basic": "^1.0",
|
|
}
|
|
}));
|
|
project_b_dir.join("main.ts").write(
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(5);
|
|
console.log(getValue());
|
|
|
|
import { add } from "project-a";
|
|
console.log(add(1, 2));
|
|
"#,
|
|
);
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run ./project-b/main.ts")
|
|
.run();
|
|
output.assert_matches_text("5\n3\n");
|
|
let output = test_context
|
|
.new_command()
|
|
.args("check ./project-b/main.ts")
|
|
.run();
|
|
output.assert_matches_text("Check file:///[WILDCARD]/project-b/main.ts\n");
|
|
|
|
// Now a file in the main directory should just be able to
|
|
// import it via node resolution even though a package.json
|
|
// doesn't exist here
|
|
dir.write(
|
|
"main.ts",
|
|
r#"
|
|
import { getValue, setValue } from "@denotest/esm-basic";
|
|
|
|
setValue(7);
|
|
console.log(getValue());
|
|
"#,
|
|
);
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text("7\n");
|
|
let output = test_context.new_command().args("check main.ts").run();
|
|
output.assert_matches_text("Check file:///[WILDCARD]/main.ts\n");
|
|
}
|
|
|
|
#[test]
|
|
fn check_css_package_json_exports() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write(
|
|
"main.ts",
|
|
r#"import "npm:@denotest/css-export/dist/index.css";"#,
|
|
);
|
|
test_context
|
|
.new_command()
|
|
.args("check main.ts")
|
|
.run()
|
|
.assert_matches_text("Download [WILDCARD]css-export\nDownload [WILDCARD]css-export/1.0.0.tgz\nCheck [WILDCARD]/main.ts\n")
|
|
.assert_exit_code(0);
|
|
}
|
|
|
|
#[test]
|
|
fn cjs_export_analysis_require_re_export() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write("deno.json", r#"{ "unstable": [ "byonm" ] }"#);
|
|
|
|
dir.write(
|
|
"package.json",
|
|
r#"{ "name": "test", "packages": { "my-package": "1.0.0" } }"#,
|
|
);
|
|
dir.write(
|
|
"main.js",
|
|
"import { value1, value2 } from 'my-package';\nconsole.log(value1);\nconsole.log(value2)\n",
|
|
);
|
|
|
|
let node_modules_dir = dir.path().join("node_modules");
|
|
|
|
// create a package at node_modules/.multipart/name/nested without a package.json
|
|
{
|
|
let pkg_dir = node_modules_dir
|
|
.join(".multipart")
|
|
.join("name")
|
|
.join("nested");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir.join("index.js").write("module.exports.value1 = 5;");
|
|
}
|
|
// create a package at node_modules/.multipart/other with a package.json
|
|
{
|
|
let pkg_dir = node_modules_dir.join(".multipart").join("other");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir.join("index.js").write("module.exports.value2 = 6;");
|
|
}
|
|
// create a package at node_modules/my-package that requires them both
|
|
{
|
|
let pkg_dir = node_modules_dir.join("my-package");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir.join("package.json").write_json(&json!({
|
|
"name": "my-package",
|
|
"version": "1.0.0",
|
|
}));
|
|
pkg_dir
|
|
.join("index.js")
|
|
.write("module.exports = { ...require('.multipart/name/nested/index'), ...require('.multipart/other/index.js') }");
|
|
}
|
|
|
|
// the cjs export analysis was previously failing, but it should
|
|
// resolve these exports similar to require
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read main.js")
|
|
.run();
|
|
output.assert_matches_text("5\n6\n");
|
|
}
|
|
|
|
#[test]
|
|
fn cjs_rexport_analysis_json() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write("deno.json", r#"{ "unstable": [ "byonm" ] }"#);
|
|
|
|
dir.write("package.json", r#"{ "name": "test" }"#);
|
|
dir.write(
|
|
"main.js",
|
|
"import data from 'my-package';\nconsole.log(data);\n",
|
|
);
|
|
|
|
let node_modules_dir = dir.path().join("node_modules");
|
|
|
|
// create a package that has a json file at index.json and data.json then folder/index.json
|
|
{
|
|
let pkg_dir = node_modules_dir.join("data-package");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir.join("package.json").write_json(&json!({
|
|
"name": "data-package",
|
|
"version": "1.0.0",
|
|
}));
|
|
pkg_dir.join("index.json").write(r#"{ "value": 2 }"#);
|
|
pkg_dir.join("data.json").write(r#"{ "value": 3 }"#);
|
|
let folder = pkg_dir.join("folder");
|
|
folder.create_dir_all();
|
|
folder.join("index.json").write(r#"{ "value": 4 }"#);
|
|
}
|
|
// create a package at node_modules/my-package that re-exports a json file
|
|
{
|
|
let pkg_dir = node_modules_dir.join("my-package");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir.join("package.json").write_json(&json!({
|
|
"name": "my-package",
|
|
"version": "1.0.0",
|
|
}));
|
|
pkg_dir.join("data.json").write(r#"{ "value": 1 }"#);
|
|
pkg_dir.join("index.js").write(
|
|
"module.exports = {
|
|
data1: require('./data'),
|
|
data2: require('data-package'),
|
|
data3: require('data-package/data'),
|
|
data4: require('data-package/folder'),
|
|
};",
|
|
);
|
|
}
|
|
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --allow-read main.js")
|
|
.run();
|
|
output.assert_matches_text(
|
|
"{
|
|
data1: { value: 1 },
|
|
data2: { value: 2 },
|
|
data3: { value: 3 },
|
|
data4: { value: 4 }
|
|
}
|
|
",
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn cjs_export_analysis_import_cjs_directly_relative_import() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let dir = test_context.temp_dir();
|
|
dir.write("deno.json", r#"{ "unstable": [ "byonm" ] }"#);
|
|
|
|
dir.write(
|
|
"package.json",
|
|
r#"{ "name": "test", "dependencies": { "@denotest/cjs-default-export": "1.0.0" } }"#,
|
|
);
|
|
// previously it wasn't doing cjs export analysis on this file
|
|
dir.write(
|
|
"main.ts",
|
|
"import { named } from './node_modules/@denotest/cjs-default-export/index.js';\nconsole.log(named());\n",
|
|
);
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context.new_command().args("run main.ts").run();
|
|
output.assert_matches_text("2\n");
|
|
}
|
|
|
|
#[test]
|
|
fn different_nested_dep_byonm() {
|
|
let test_context = TestContextBuilder::for_npm()
|
|
.use_copy_temp_dir("npm/different_nested_dep")
|
|
.cwd("npm/different_nested_dep/")
|
|
.build();
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context
|
|
.new_command()
|
|
.args("run --unstable-byonm main.js")
|
|
.run();
|
|
output.assert_matches_file("npm/different_nested_dep/main.out");
|
|
}
|
|
|
|
#[test]
|
|
fn different_nested_dep_byonm_future() {
|
|
let test_context = TestContextBuilder::for_npm()
|
|
.use_copy_temp_dir("npm/different_nested_dep")
|
|
.cwd("npm/different_nested_dep/")
|
|
.build();
|
|
|
|
test_context.run_npm("install");
|
|
|
|
let output = test_context.new_command().args("run main.js").run();
|
|
output.assert_matches_file("npm/different_nested_dep/main.out");
|
|
}
|
|
|
|
#[test]
|
|
fn run_cjs_in_node_modules_folder() {
|
|
let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
|
let temp_dir = test_context.temp_dir();
|
|
temp_dir.write("package.json", "{}");
|
|
temp_dir.write("deno.json", r#"{ "unstable": ["byonm"] }"#);
|
|
let pkg_dir = temp_dir.path().join("node_modules/package");
|
|
pkg_dir.create_dir_all();
|
|
pkg_dir
|
|
.join("package.json")
|
|
.write(r#"{ "name": "package" }"#);
|
|
pkg_dir
|
|
.join("main.js")
|
|
.write("console.log('hi'); module.exports = 'hi';");
|
|
test_context
|
|
.new_command()
|
|
.args("run node_modules/package/main.js")
|
|
.run()
|
|
.assert_matches_text("hi\n");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_private_npm_registry() {
|
|
let _server = http_server();
|
|
|
|
// For now just check that private server rejects requests without proper
|
|
// auth header.
|
|
|
|
let client = reqwest::Client::new();
|
|
|
|
let url = Url::parse("http://127.0.0.1:4261/@denotest/basic").unwrap();
|
|
|
|
let req = reqwest::Request::new(reqwest::Method::GET, url.clone());
|
|
let resp = client.execute(req).await.unwrap();
|
|
assert_eq!(resp.status(), reqwest::StatusCode::UNAUTHORIZED);
|
|
|
|
let mut req = reqwest::Request::new(reqwest::Method::GET, url.clone());
|
|
req.headers_mut().insert(
|
|
reqwest::header::AUTHORIZATION,
|
|
reqwest::header::HeaderValue::from_static("Bearer private-reg-token"),
|
|
);
|
|
let resp = client.execute(req).await.unwrap();
|
|
assert_eq!(resp.status(), reqwest::StatusCode::OK);
|
|
}
|