mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat(cli): Add deno cache --test and --worker (#7920)
This commit is contained in:
parent
29e05bb014
commit
be15cf285d
6 changed files with 176 additions and 27 deletions
95
cli/flags.rs
95
cli/flags.rs
|
@ -3,6 +3,7 @@
|
|||
use clap::App;
|
||||
use clap::AppSettings;
|
||||
use clap::Arg;
|
||||
use clap::ArgGroup;
|
||||
use clap::ArgMatches;
|
||||
use clap::ArgSettings;
|
||||
use clap::SubCommand;
|
||||
|
@ -37,6 +38,8 @@ pub enum DenoSubcommand {
|
|||
},
|
||||
Cache {
|
||||
files: Vec<String>,
|
||||
worker_specifiers: Option<Vec<String>>,
|
||||
test_patterns: Option<Vec<String>>,
|
||||
},
|
||||
Fmt {
|
||||
check: bool,
|
||||
|
@ -481,10 +484,20 @@ fn cache_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
compile_args_parse(flags, matches);
|
||||
let files = matches
|
||||
.values_of("file")
|
||||
.unwrap()
|
||||
.unwrap_or_default()
|
||||
.map(String::from)
|
||||
.collect();
|
||||
flags.subcommand = DenoSubcommand::Cache { files };
|
||||
let worker_specifiers = matches
|
||||
.values_of("worker")
|
||||
.map(|v| v.map(String::from).collect());
|
||||
let test_patterns = matches
|
||||
.values_of("test")
|
||||
.map(|v| v.map(String::from).collect());
|
||||
flags.subcommand = DenoSubcommand::Cache {
|
||||
files,
|
||||
worker_specifiers,
|
||||
test_patterns,
|
||||
};
|
||||
}
|
||||
|
||||
fn lock_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||
|
@ -871,11 +884,31 @@ TypeScript compiler cache: Subdirectory containing TS compiler output.",
|
|||
|
||||
fn cache_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||
compile_args(SubCommand::with_name("cache"))
|
||||
.arg(Arg::with_name("file").takes_value(true).multiple(true))
|
||||
.arg(
|
||||
Arg::with_name("file")
|
||||
Arg::with_name("worker")
|
||||
.long("worker")
|
||||
.help("Compile <WORKER_SPECIFIERS> as Deno web workers")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
.min_values(1),
|
||||
.value_name("WORKER_SPECIFIERS")
|
||||
.min_values(1)
|
||||
.use_delimiter(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("test")
|
||||
.long("test")
|
||||
.help("Includes files captured by: deno test <PATTERN_LIST>")
|
||||
.takes_value(true)
|
||||
.value_name("PATTERN_LIST")
|
||||
.min_values(0)
|
||||
.use_delimiter(true)
|
||||
.require_equals(true),
|
||||
)
|
||||
.group(
|
||||
ArgGroup::with_name("target")
|
||||
.args(&["file", "test", "worker"])
|
||||
.multiple(true)
|
||||
.required(true),
|
||||
)
|
||||
.about("Cache the dependencies")
|
||||
.long_about(
|
||||
|
@ -1913,6 +1946,52 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec!["script.ts"],
|
||||
worker_specifiers: None,
|
||||
test_patterns: None,
|
||||
},
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
||||
let r = flags_from_vec_safe(svec!["deno", "cache", "--test"]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec![],
|
||||
worker_specifiers: None,
|
||||
test_patterns: Some(svec![]),
|
||||
},
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
||||
let r = flags_from_vec_safe(svec!["deno", "cache", "--test=a,b"]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec![],
|
||||
test_patterns: Some(svec!["a", "b"]),
|
||||
worker_specifiers: None,
|
||||
},
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
|
||||
let r = flags_from_vec_safe(svec![
|
||||
"deno",
|
||||
"cache",
|
||||
"--worker",
|
||||
"worker1.ts,worker2.ts"
|
||||
]);
|
||||
assert_eq!(
|
||||
r.unwrap(),
|
||||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec![],
|
||||
test_patterns: None,
|
||||
worker_specifiers: Some(svec!["worker1.ts", "worker2.ts"]),
|
||||
},
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -2414,6 +2493,8 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec!["script.ts"],
|
||||
worker_specifiers: None,
|
||||
test_patterns: None,
|
||||
},
|
||||
unstable: true,
|
||||
import_map_path: Some("import_map.json".to_owned()),
|
||||
|
@ -2456,6 +2537,8 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec!["script.ts", "script_two.ts"],
|
||||
worker_specifiers: None,
|
||||
test_patterns: None,
|
||||
},
|
||||
..Flags::default()
|
||||
}
|
||||
|
@ -2979,6 +3062,8 @@ mod tests {
|
|||
Flags {
|
||||
subcommand: DenoSubcommand::Cache {
|
||||
files: svec!["script.ts", "script_two.ts"],
|
||||
worker_specifiers: None,
|
||||
test_patterns: None,
|
||||
},
|
||||
ca_file: Some("example.crt".to_owned()),
|
||||
..Flags::default()
|
||||
|
|
88
cli/main.rs
88
cli/main.rs
|
@ -94,6 +94,7 @@ use std::pin::Pin;
|
|||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use upgrade::upgrade_command;
|
||||
use worker::WebWorker;
|
||||
|
||||
fn write_to_stdout_ignore_sigpipe(bytes: &[u8]) -> Result<(), std::io::Error> {
|
||||
use std::io::ErrorKind;
|
||||
|
@ -236,6 +237,8 @@ async fn lint_command(
|
|||
async fn cache_command(
|
||||
flags: Flags,
|
||||
files: Vec<String>,
|
||||
worker_specifiers: Option<Vec<String>>,
|
||||
test_patterns: Option<Vec<String>>,
|
||||
) -> Result<(), AnyError> {
|
||||
let main_module =
|
||||
ModuleSpecifier::resolve_url_or_path("./$deno$cache.ts").unwrap();
|
||||
|
@ -249,6 +252,48 @@ async fn cache_command(
|
|||
worker.preload_module(&specifier).await.map(|_| ())?;
|
||||
}
|
||||
|
||||
if let Some(worker_specifiers) = worker_specifiers {
|
||||
let mut web_worker = WebWorker::new(
|
||||
"".to_string(),
|
||||
Permissions::allow_all(),
|
||||
main_module,
|
||||
program_state.clone(),
|
||||
true,
|
||||
);
|
||||
for specifier in worker_specifiers {
|
||||
let specifier = ModuleSpecifier::resolve_url_or_path(&specifier)?;
|
||||
web_worker.preload_module(&specifier).await.map(|_| ())?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(test_patterns) = test_patterns {
|
||||
let cwd = std::env::current_dir().expect("No current directory");
|
||||
let mut include = test_patterns;
|
||||
if include.is_empty() {
|
||||
include.push(".".to_string());
|
||||
}
|
||||
let specifier = ModuleSpecifier::resolve_path("$deno$test.ts")?;
|
||||
// Create a dummy source file.
|
||||
let source_file = SourceFile {
|
||||
filename: specifier.as_url().to_file_path().unwrap(),
|
||||
url: specifier.as_url().clone(),
|
||||
types_header: None,
|
||||
media_type: MediaType::TypeScript,
|
||||
source_code: test_runner::render_test_file(
|
||||
test_runner::prepare_test_modules_urls(include, &cwd)?,
|
||||
false,
|
||||
false,
|
||||
None,
|
||||
),
|
||||
};
|
||||
// Save our fake file into file fetcher cache
|
||||
// to allow module access by TS compiler
|
||||
program_state
|
||||
.file_fetcher
|
||||
.save_source_file_in_cache(&specifier, source_file);
|
||||
worker.preload_module(&specifier).await.map(|_| ())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -632,26 +677,19 @@ async fn test_command(
|
|||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let test_file_path = cwd.join("$deno$test.ts");
|
||||
let test_file_url =
|
||||
Url::from_file_path(&test_file_path).expect("Should be valid file url");
|
||||
let test_file = test_runner::render_test_file(
|
||||
let main_module = ModuleSpecifier::resolve_path("$deno$test.ts")?;
|
||||
// Create a dummy source file.
|
||||
let source_file = SourceFile {
|
||||
filename: main_module.as_url().to_file_path().unwrap(),
|
||||
url: main_module.as_url().clone(),
|
||||
types_header: None,
|
||||
media_type: MediaType::TypeScript,
|
||||
source_code: test_runner::render_test_file(
|
||||
test_modules.clone(),
|
||||
fail_fast,
|
||||
quiet,
|
||||
filter,
|
||||
);
|
||||
let main_module =
|
||||
ModuleSpecifier::resolve_url(&test_file_url.to_string()).unwrap();
|
||||
let mut worker = MainWorker::new(&program_state, main_module.clone());
|
||||
// Create a dummy source file.
|
||||
let source_file = SourceFile {
|
||||
filename: test_file_url.to_file_path().unwrap(),
|
||||
url: test_file_url.clone(),
|
||||
types_header: None,
|
||||
media_type: MediaType::TypeScript,
|
||||
source_code: test_file.clone(),
|
||||
),
|
||||
};
|
||||
// Save our fake file into file fetcher cache
|
||||
// to allow module access by TS compiler
|
||||
|
@ -659,6 +697,8 @@ async fn test_command(
|
|||
.file_fetcher
|
||||
.save_source_file_in_cache(&main_module, source_file);
|
||||
|
||||
let mut worker = MainWorker::new(&program_state, main_module.clone());
|
||||
|
||||
let mut maybe_coverage_collector = if flags.coverage {
|
||||
let session = worker.create_inspector_session();
|
||||
let mut coverage_collector = CoverageCollector::new(session);
|
||||
|
@ -680,8 +720,11 @@ async fn test_command(
|
|||
let coverages = coverage_collector.collect().await?;
|
||||
coverage_collector.stop_collecting().await?;
|
||||
|
||||
let filtered_coverages =
|
||||
coverage::filter_script_coverages(coverages, test_file_url, test_modules);
|
||||
let filtered_coverages = coverage::filter_script_coverages(
|
||||
coverages,
|
||||
main_module.as_url().clone(),
|
||||
test_modules,
|
||||
);
|
||||
|
||||
let mut coverage_reporter = PrettyCoverageReporter::new(quiet);
|
||||
for coverage in filtered_coverages {
|
||||
|
@ -771,9 +814,12 @@ pub fn main() {
|
|||
code,
|
||||
as_typescript,
|
||||
} => eval_command(flags, code, as_typescript, print).boxed_local(),
|
||||
DenoSubcommand::Cache { files } => {
|
||||
cache_command(flags, files).boxed_local()
|
||||
}
|
||||
DenoSubcommand::Cache {
|
||||
files,
|
||||
worker_specifiers,
|
||||
test_patterns,
|
||||
} => cache_command(flags, files, worker_specifiers, test_patterns)
|
||||
.boxed_local(),
|
||||
DenoSubcommand::Fmt {
|
||||
check,
|
||||
files,
|
||||
|
|
4
cli/tests/068_cache_test_type_error.out
Normal file
4
cli/tests/068_cache_test_type_error.out
Normal file
|
@ -0,0 +1,4 @@
|
|||
[WILDCARD]error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
const a: string = 1;
|
||||
^
|
||||
at [WILDCARD]foo_test.ts[WILDCARD]
|
|
@ -2137,6 +2137,18 @@ fn _066_prompt() {
|
|||
util::test_pty(args, output, input);
|
||||
}
|
||||
|
||||
itest!(_068_cache_test_type_error {
|
||||
args: "cache --test=test_type_error",
|
||||
output: "068_cache_test_type_error.out",
|
||||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(_069_cache_worker {
|
||||
args: "cache --worker subdir/worker_globals.ts",
|
||||
output_str: Some("[WILDCARD]"),
|
||||
exit_code: 0,
|
||||
});
|
||||
|
||||
itest!(_073_worker_error {
|
||||
args: "run -A 073_worker_error.ts",
|
||||
output: "073_worker_error.ts.out",
|
||||
|
|
2
cli/tests/test_type_error/foo_test.ts
Normal file
2
cli/tests/test_type_error/foo_test.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
/* eslint-disable */
|
||||
const a: string = 1;
|
|
@ -149,7 +149,7 @@ impl ModuleSpecifier {
|
|||
/// Converts a string representing a relative or absolute path into a
|
||||
/// ModuleSpecifier. A relative path is considered relative to the current
|
||||
/// working directory.
|
||||
fn resolve_path(
|
||||
pub fn resolve_path(
|
||||
path_str: &str,
|
||||
) -> Result<ModuleSpecifier, ModuleResolutionError> {
|
||||
let path = current_dir().unwrap().join(path_str);
|
||||
|
|
Loading…
Reference in a new issue