1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 07:44:48 -05:00
denoland-deno/cli/tests/integration/npm_tests.rs

1799 lines
58 KiB
Rust

// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_core::serde_json;
use deno_core::serde_json::Value;
use pretty_assertions::assert_eq;
use std::process::Stdio;
use test_util as util;
use util::assert_contains;
use util::env_vars_for_npm_tests;
use util::env_vars_for_npm_tests_no_sync_download;
use util::http_server;
use util::TestContextBuilder;
// NOTE: See how to make test npm packages at ./testdata/npm/README.md
itest!(esm_module {
args: "run --allow-read --allow-env npm/esm/main.js",
output: "npm/esm/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(esm_module_eval {
args_vec: vec![
"eval",
"import chalk from 'npm:chalk@5'; console.log(chalk.green('chalk esm loads'));",
],
output: "npm/esm/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(esm_module_deno_test {
args: "test --allow-read --allow-env --unstable npm/esm/test.js",
output: "npm/esm/test.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(esm_import_cjs_default {
args: "run --allow-read --allow-env --unstable --quiet --check=all npm/esm_import_cjs_default/main.ts",
output: "npm/esm_import_cjs_default/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_with_deps {
args: "run --allow-read --allow-env npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_sub_path {
args: "run --allow-read npm/cjs_sub_path/main.js",
output: "npm/cjs_sub_path/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_local_global_decls {
args: "run --allow-read npm/cjs_local_global_decls/main.ts",
output: "npm/cjs_local_global_decls/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_reexport_collision {
args: "run -A --quiet npm/cjs_reexport_collision/main.ts",
output: "npm/cjs_reexport_collision/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_this_in_exports {
args: "run --allow-read --quiet npm/cjs_this_in_exports/main.js",
output: "npm/cjs_this_in_exports/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(translate_cjs_to_esm {
args: "run -A --quiet npm/translate_cjs_to_esm/main.js",
output: "npm/translate_cjs_to_esm/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(compare_globals {
args: "run --allow-read --unstable --check=all npm/compare_globals/main.ts",
output: "npm/compare_globals/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(conditional_exports {
args: "run --allow-read npm/conditional_exports/main.js",
output: "npm/conditional_exports/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(conditional_exports_node_modules_dir {
args:
"run --allow-read --node-modules-dir $TESTDATA/npm/conditional_exports/main.js",
output: "npm/conditional_exports/main_node_modules.out",
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
itest!(dual_cjs_esm {
args: "run -A --quiet npm/dual_cjs_esm/main.ts",
output: "npm/dual_cjs_esm/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(child_process_fork_test {
args: "run -A --quiet npm/child_process_fork_test/main.ts",
output: "npm/child_process_fork_test/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_module_export_assignment {
args: "run -A --unstable --quiet --check=all npm/cjs_module_export_assignment/main.ts",
output: "npm/cjs_module_export_assignment/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(cjs_module_export_assignment_number {
args: "run -A --unstable --quiet --check=all npm/cjs_module_export_assignment_number/main.ts",
output: "npm/cjs_module_export_assignment_number/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(mixed_case_package_name_global_dir {
args: "run npm/mixed_case_package_name/global.ts",
output: "npm/mixed_case_package_name/global.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(mixed_case_package_name_local_dir {
args:
"run --node-modules-dir -A $TESTDATA/npm/mixed_case_package_name/local.ts",
output: "npm/mixed_case_package_name/local.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
// 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!(dynamic_import_reload_same_package {
args: "run -A --reload npm/dynamic_import_reload_same_package/main.ts",
output: "npm/dynamic_import_reload_same_package/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(env_var_re_export_dev {
args: "run --allow-read --allow-env --quiet npm/env_var_re_export/main.js",
output_str: Some("dev\n"),
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(env_var_re_export_prod {
args: "run --allow-read --allow-env --quiet npm/env_var_re_export/main.js",
output_str: Some("prod\n"),
envs: {
let mut vars = env_vars_for_npm_tests();
vars.push(("NODE_ENV".to_string(), "production".to_string()));
vars
},
http_server: true,
});
itest!(cached_only {
args: "run --cached-only npm/cached_only/main.ts",
output: "npm/cached_only/main.out",
envs: env_vars_for_npm_tests(),
exit_code: 1,
});
itest!(import_map {
args: "run --allow-read --allow-env --import-map npm/import_map/import_map.json npm/import_map/main.js",
output: "npm/import_map/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(lock_file {
args: "run --allow-read --allow-env --lock npm/lock_file/lock.json npm/lock_file/main.js",
output: "npm/lock_file/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 10,
});
itest!(sub_paths {
args: "run -A --quiet npm/sub_paths/main.jsx",
output: "npm/sub_paths/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(remote_npm_specifier {
args: "run --quiet -A npm/remote_npm_specifier/main.ts",
output: "npm/remote_npm_specifier/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 0,
});
itest!(tarball_with_global_header {
args: "run -A --quiet npm/tarball_with_global_header/main.js",
output: "npm/tarball_with_global_header/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(nonexistent_file {
args: "run -A --quiet npm/nonexistent_file/main.js",
output: "npm/nonexistent_file/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(invalid_package_name {
args: "run -A --quiet npm/invalid_package_name/main.js",
output: "npm/invalid_package_name/main.out",
envs: env_vars_for_npm_tests(),
exit_code: 1,
});
itest!(require_json {
args: "run -A --quiet npm/require_json/main.js",
output: "npm/require_json/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(error_version_after_subpath {
args: "run -A --quiet npm/error_version_after_subpath/main.js",
output: "npm/error_version_after_subpath/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(deno_cache {
args: "cache --reload npm:chalk npm:mkdirp",
output: "npm/deno_cache.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(check_all {
args: "check --all npm/check_errors/main.ts",
output: "npm/check_errors/main_all.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(check_local {
args: "check npm/check_errors/main.ts",
output: "npm/check_errors/main_local.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(types_general {
args: "check --quiet npm/types/main.ts",
output: "npm/types/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(types_ambient_module {
args: "check --quiet npm/types_ambient_module/main.ts",
output: "npm/types_ambient_module/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(types_ambient_module_import_map {
args: "check --quiet --import-map=npm/types_ambient_module/import_map.json npm/types_ambient_module/main_import_map.ts",
output: "npm/types_ambient_module/main_import_map.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(no_types_cjs {
args: "check --quiet npm/no_types_cjs/main.ts",
output_str: Some(""),
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(no_types_in_conditional_exports {
args: "run --check --unstable npm/no_types_in_conditional_exports/main.ts",
output: "npm/no_types_in_conditional_exports/main.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(types_entry_value_not_exists {
args: "check --all npm/types_entry_value_not_exists/main.ts",
output: "npm/types_entry_value_not_exists/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(types_exports_import_types {
args: "check --all npm/types_exports_import_types/main.ts",
output: "npm/types_exports_import_types/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(types_no_types_entry {
args: "check --all npm/types_no_types_entry/main.ts",
output: "npm/types_no_types_entry/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(typescript_file_in_package {
args: "run npm/typescript_file_in_package/main.ts",
output: "npm/typescript_file_in_package/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(permissions_outside_package {
args: "run --allow-read npm/permissions_outside_package/main.ts",
output: "npm/permissions_outside_package/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
#[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_no_sync_download()),
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
}
#[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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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, "createChalk: chalk");
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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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());
}
itest!(deno_run_cowsay {
args: "run -A --quiet npm:cowsay@1.5.0 Hello",
output: "npm/deno_run_cowsay.out",
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
itest!(deno_run_cowsay_with_node_modules_dir {
args: "run -A --quiet --node-modules-dir npm:cowsay@1.5.0 Hello",
temp_cwd: true,
output: "npm/deno_run_cowsay.out",
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
itest!(deno_run_cowsay_explicit {
args: "run -A --quiet npm:cowsay@1.5.0/cowsay Hello",
output: "npm/deno_run_cowsay.out",
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
itest!(deno_run_cowthink {
args: "run -A --quiet npm:cowsay@1.5.0/cowthink Hello",
output: "npm/deno_run_cowthink.out",
envs: env_vars_for_npm_tests_no_sync_download(),
http_server: true,
});
itest!(deno_run_bin_esm {
args: "run -A --quiet npm:@denotest/bin/cli-esm this is a test",
output: "npm/deno_run_esm.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(deno_run_bin_special_chars {
args: "run -A --quiet npm:@denotest/special-chars-in-bin-name/\\foo\" this is a test",
output: "npm/deno_run_special_chars_in_bin_name.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(deno_run_bin_no_ext {
args: "run -A --quiet npm:@denotest/bin/cli-no-ext this is a test",
output: "npm/deno_run_no_ext.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(deno_run_bin_cjs {
args: "run -A --quiet npm:@denotest/bin/cli-cjs this is a test",
output: "npm/deno_run_cjs.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(deno_run_non_existent {
args: "run npm:mkdirp@0.5.125",
output: "npm/deno_run_non_existent.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
});
itest!(builtin_module_module {
args: "run --allow-read --quiet npm/builtin_module_module/main.js",
output: "npm/builtin_module_module/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(node_modules_dir_require_added_node_modules_folder {
args:
"run --node-modules-dir -A --quiet $TESTDATA/npm/require_added_nm_folder/main.js",
output: "npm/require_added_nm_folder/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 0,
temp_cwd: true,
});
itest!(node_modules_dir_require_main_entry {
args: "run --node-modules-dir -A --quiet $TESTDATA/npm/require_main/main.js",
output: "npm/require_main/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 0,
temp_cwd: true,
});
itest!(node_modules_dir_with_deps {
args: "run --allow-read --allow-env --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main_node_modules.out",
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
itest!(node_modules_dir_yargs {
args: "run --allow-read --allow-env --node-modules-dir $TESTDATA/npm/cjs_yargs/main.js",
output: "npm/cjs_yargs/main.out",
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
#[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")
.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_4545")
.join("npm")
.join("registry")
.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")
.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::testdata_path().join("npm").join("registry");
for entry in std::fs::read_dir(&registry_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(&registry_json_path).unwrap();
if file_text.contains("https://registry.npmjs.org/") {
panic!(
"file {} contained a reference to the npm registry",
registry_json_path.display(),
);
}
}
}
}
}
itest!(compile_errors {
args: "compile -A --quiet npm/cached_only/main.ts",
output_str: Some("error: npm specifiers have not yet been implemented for this sub command (https://github.com/denoland/deno/issues/15960). Found: npm:chalk@5.0.1\n"),
exit_code: 1,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(bundle_errors {
args: "bundle --quiet npm/esm/main.js",
output_str: Some("error: npm specifiers have not yet been implemented for this sub command (https://github.com/denoland/deno/issues/15960). Found: npm:chalk@5.0.1\n"),
exit_code: 1,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(info_chalk_display {
args: "info --quiet npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main_info.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(info_chalk_display_node_modules_dir {
args: "info --quiet --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main_info.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
itest!(info_chalk_json {
args: "info --quiet --json npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main_info_json.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(info_chalk_json_node_modules_dir {
args:
"info --quiet --node-modules-dir --json $TESTDATA/npm/cjs_with_deps/main.js",
output: "npm/cjs_with_deps/main_info_json.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
temp_cwd: true,
});
itest!(info_cli_chalk_display {
args: "info --quiet npm:chalk@4",
output: "npm/info/chalk.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(info_cli_chalk_json {
args: "info --quiet --json npm:chalk@4",
output: "npm/info/chalk_json.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
#[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())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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. You can recreate it with --lock-write\n",
" 1: Could not find referenced package 'cowsay@1.5.0' in the list of packages.\n"
)
);
}
#[test]
fn lock_file_lock_write() {
// https://github.com/denoland/deno/issues/16666
// Ensure that --lock-write still adds npm packages to the lockfile
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", "{}");
// write a lock file with borked integrity
let lock_file_content = r#"{
"version": "2",
"remote": {},
"npm": {
"specifiers": {
"cowsay@1.5.0": "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": {}
},
"cowsay@1.5.0": {
"integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==",
"dependencies": {
"get-stdin": "get-stdin@8.0.0",
"string-width": "string-width@2.1.1",
"strip-final-newline": "strip-final-newline@2.0.0",
"yargs": "yargs@15.4.1"
}
},
"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 deno = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(temp_dir.path())
.arg("cache")
.arg("--lock-write")
.arg("--quiet")
.arg("npm:cowsay@1.5.0")
.envs(env_vars_for_npm_tests())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.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!(
lock_file_content,
std::fs::read_to_string(temp_dir.path().join("deno.lock")).unwrap()
);
}
#[test]
fn auto_discover_lock_file() {
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", "{}");
// write a lock file with borked integrity
let lock_file_content = r#"{
"version": "2",
"remote": {},
"npm": {
"specifiers": { "@denotest/bin": "@denotest/bin@1.0.0" },
"packages": {
"@denotest/bin@1.0.0": {
"integrity": "sha512-foobar",
"dependencies": {}
}
}
}
}"#;
temp_dir.write("deno.lock", lock_file_content);
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
.current_dir(temp_dir.path())
.arg("run")
.arg("--unstable")
.arg("-A")
.arg("npm:@denotest/bin/cli-esm")
.arg("test")
.envs(env_vars_for_npm_tests())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let output = deno.wait_with_output().unwrap();
assert!(!output.status.success());
assert_eq!(output.status.code(), Some(10));
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(
"Integrity check failed for npm package: \"@denotest/bin@1.0.0\""
));
}
#[test]
fn peer_deps_with_copied_folders_and_lockfile() {
let context = TestContextBuilder::for_npm()
.use_sync_npm_download()
.use_separate_deno_dir() // the "npm" folder means something in the deno dir, so use a separate folder
.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_4545")
.join("npm")
.join("registry")
.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 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 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 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 --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",
);
}
itest!(info_peer_deps {
args: "info --quiet npm/peer_deps_with_copied_folders/main.ts",
output: "npm/peer_deps_with_copied_folders/main_info.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(info_peer_deps_json {
args: "info --quiet --json npm/peer_deps_with_copied_folders/main.ts",
output: "npm/peer_deps_with_copied_folders/main_info_json.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
itest!(create_require {
args: "run --reload --allow-read npm/create_require/main.ts",
output: "npm/create_require/main.out",
exit_code: 0,
envs: env_vars_for_npm_tests(),
http_server: true,
});
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,
});
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,
});
itest!(non_existent_dep {
args: "cache npm:@denotest/non-existent-dep",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
output_str: Some(concat!(
"Download http://localhost:4545/npm/registry/@denotest/non-existent-dep\n",
"Download http://localhost:4545/npm/registry/@denotest/non-existent\n",
"error: npm package '@denotest/non-existent' does not exist.\n"
)),
});
itest!(non_existent_dep_version {
args: "cache npm:@denotest/non-existent-dep-version",
envs: env_vars_for_npm_tests(),
http_server: true,
exit_code: 1,
output_str: Some(concat!(
"Download http://localhost:4545/npm/registry/@denotest/non-existent-dep-version\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
// does two downloads because when failing once it max tries to
// get the latest version a second time
"Download http://localhost:4545/npm/registry/@denotest/non-existent-dep-version\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
"error: Could not find npm package '@denotest/esm-basic' matching '=99.99.99'.\n"
)),
});
#[test]
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_4545/npm/registry/{}/registry.json", package);
let mut registry_json: Value =
serde_json::from_str(&deno_dir.read_to_string(&registry_json_path))
.unwrap();
remove_version(&mut registry_json, version);
deno_dir.write(
&registry_json_path,
serde_json::to_string(&registry_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_sync_npm_download()
.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!(
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export/1.0.0.tgz\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-basic/1.0.0.tgz\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default/1.0.0.tgz\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!(
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\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!(
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\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",
));
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!(
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
"Initialize @denotest/cjs-default-export@1.0.0\n",
"Initialize @denotest/esm-import-cjs-default@1.0.0\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!(
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\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("cache 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",
" Could not find '@denotest/esm-basic@1.0.0' specified in the lockfile.\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!(
"Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
"Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n",
"Node esm importing node cjs\n[WILDCARD]",
));
output.assert_exit_code(0);
}
}