mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
feat(unstable): Add deno test --no-run (#8093)
This commit adds new flag to "deno test" subcommand called "--no-run" that allows to preload, cache an type check.
This commit is contained in:
parent
686a17fc07
commit
14877f7fe2
7 changed files with 98 additions and 155 deletions
114
cli/flags.rs
114
cli/flags.rs
|
@ -66,6 +66,7 @@ pub enum DenoSubcommand {
|
||||||
script: String,
|
script: String,
|
||||||
},
|
},
|
||||||
Test {
|
Test {
|
||||||
|
no_run: bool,
|
||||||
fail_fast: bool,
|
fail_fast: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
allow_none: bool,
|
allow_none: bool,
|
||||||
|
@ -572,8 +573,9 @@ fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
runtime_args_parse(flags, matches, true);
|
runtime_args_parse(flags, matches, true);
|
||||||
|
|
||||||
|
let no_run = matches.is_present("no-run");
|
||||||
let failfast = matches.is_present("failfast");
|
let failfast = matches.is_present("failfast");
|
||||||
let allow_none = matches.is_present("allow_none");
|
let allow_none = matches.is_present("allow-none");
|
||||||
let quiet = matches.is_present("quiet");
|
let quiet = matches.is_present("quiet");
|
||||||
let filter = matches.value_of("filter").map(String::from);
|
let filter = matches.value_of("filter").map(String::from);
|
||||||
let coverage = matches.is_present("coverage");
|
let coverage = matches.is_present("coverage");
|
||||||
|
@ -606,6 +608,7 @@ fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
};
|
};
|
||||||
|
|
||||||
flags.subcommand = DenoSubcommand::Test {
|
flags.subcommand = DenoSubcommand::Test {
|
||||||
|
no_run,
|
||||||
fail_fast: failfast,
|
fail_fast: failfast,
|
||||||
quiet,
|
quiet,
|
||||||
include,
|
include,
|
||||||
|
@ -1147,6 +1150,13 @@ Deno allows specifying the filename '-' to read the file from stdin.
|
||||||
fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
runtime_args(SubCommand::with_name("test"), true)
|
runtime_args(SubCommand::with_name("test"), true)
|
||||||
.setting(AppSettings::TrailingVarArg)
|
.setting(AppSettings::TrailingVarArg)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("no-run")
|
||||||
|
.long("no-run")
|
||||||
|
.help("Cache test modules, but don't run tests")
|
||||||
|
.takes_value(false)
|
||||||
|
.requires("unstable"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("failfast")
|
Arg::with_name("failfast")
|
||||||
.long("failfast")
|
.long("failfast")
|
||||||
|
@ -1154,7 +1164,7 @@ fn test_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("allow_none")
|
Arg::with_name("allow-none")
|
||||||
.long("allow-none")
|
.long("allow-none")
|
||||||
.help("Don't return error code if no test files are found")
|
.help("Don't return error code if no test files are found")
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
|
@ -2838,109 +2848,23 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_with_allow_net() {
|
fn test_with_flags() {
|
||||||
let r = flags_from_vec_safe(svec![
|
#[rustfmt::skip]
|
||||||
"deno",
|
let r = flags_from_vec_safe(svec!["deno", "test", "--unstable", "--no-run", "--filter", "- foo", "--coverage", "--allow-net", "--allow-none", "dir1/", "dir2/", "--", "arg1", "arg2"]);
|
||||||
"test",
|
|
||||||
"--allow-net",
|
|
||||||
"--allow-none",
|
|
||||||
"dir1/",
|
|
||||||
"dir2/"
|
|
||||||
]);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
Flags {
|
Flags {
|
||||||
subcommand: DenoSubcommand::Test {
|
subcommand: DenoSubcommand::Test {
|
||||||
|
no_run: true,
|
||||||
fail_fast: false,
|
fail_fast: false,
|
||||||
filter: None,
|
filter: Some("- foo".to_string()),
|
||||||
allow_none: true,
|
allow_none: true,
|
||||||
quiet: false,
|
quiet: false,
|
||||||
include: Some(svec!["dir1/", "dir2/"]),
|
include: Some(svec!["dir1/", "dir2/"]),
|
||||||
},
|
},
|
||||||
allow_net: true,
|
|
||||||
..Flags::default()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_filter() {
|
|
||||||
let r = flags_from_vec_safe(svec!["deno", "test", "--filter=foo", "dir1"]);
|
|
||||||
assert_eq!(
|
|
||||||
r.unwrap(),
|
|
||||||
Flags {
|
|
||||||
subcommand: DenoSubcommand::Test {
|
|
||||||
fail_fast: false,
|
|
||||||
allow_none: false,
|
|
||||||
quiet: false,
|
|
||||||
filter: Some("foo".to_string()),
|
|
||||||
include: Some(svec!["dir1"]),
|
|
||||||
},
|
|
||||||
..Flags::default()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_filter_leading_hyphen() {
|
|
||||||
let r =
|
|
||||||
flags_from_vec_safe(svec!["deno", "test", "--filter", "- foo", "dir1"]);
|
|
||||||
assert_eq!(
|
|
||||||
r.unwrap(),
|
|
||||||
Flags {
|
|
||||||
subcommand: DenoSubcommand::Test {
|
|
||||||
fail_fast: false,
|
|
||||||
allow_none: false,
|
|
||||||
quiet: false,
|
|
||||||
filter: Some("- foo".to_string()),
|
|
||||||
include: Some(svec!["dir1"]),
|
|
||||||
},
|
|
||||||
..Flags::default()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_coverage() {
|
|
||||||
let r = flags_from_vec_safe(svec![
|
|
||||||
"deno",
|
|
||||||
"test",
|
|
||||||
"--unstable",
|
|
||||||
"--coverage",
|
|
||||||
"dir1"
|
|
||||||
]);
|
|
||||||
assert_eq!(
|
|
||||||
r.unwrap(),
|
|
||||||
Flags {
|
|
||||||
subcommand: DenoSubcommand::Test {
|
|
||||||
fail_fast: false,
|
|
||||||
allow_none: false,
|
|
||||||
quiet: false,
|
|
||||||
filter: None,
|
|
||||||
include: Some(svec!["dir1"]),
|
|
||||||
},
|
|
||||||
coverage: true,
|
|
||||||
unstable: true,
|
unstable: true,
|
||||||
..Flags::default()
|
coverage: true,
|
||||||
}
|
allow_net: true,
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_double_hyphen() {
|
|
||||||
let r = flags_from_vec_safe(svec![
|
|
||||||
"deno", "test", "test.ts", "--", "arg1", "arg2"
|
|
||||||
]);
|
|
||||||
assert_eq!(
|
|
||||||
r.unwrap(),
|
|
||||||
Flags {
|
|
||||||
subcommand: DenoSubcommand::Test {
|
|
||||||
fail_fast: false,
|
|
||||||
allow_none: false,
|
|
||||||
quiet: false,
|
|
||||||
filter: None,
|
|
||||||
include: Some(svec!["test.ts"]),
|
|
||||||
},
|
|
||||||
argv: svec!["arg1", "arg2"],
|
argv: svec!["arg1", "arg2"],
|
||||||
..Flags::default()
|
..Flags::default()
|
||||||
}
|
}
|
||||||
|
|
58
cli/main.rs
58
cli/main.rs
|
@ -60,7 +60,6 @@ use deno_core::futures::future::FutureExt;
|
||||||
use deno_core::futures::Future;
|
use deno_core::futures::Future;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::url::Url;
|
|
||||||
use deno_core::v8_set_flags;
|
use deno_core::v8_set_flags;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_doc as doc;
|
use deno_doc as doc;
|
||||||
|
@ -625,6 +624,7 @@ async fn run_command(flags: Flags, script: String) -> Result<(), AnyError> {
|
||||||
async fn test_command(
|
async fn test_command(
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
include: Option<Vec<String>>,
|
include: Option<Vec<String>>,
|
||||||
|
no_run: bool,
|
||||||
fail_fast: bool,
|
fail_fast: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
allow_none: bool,
|
allow_none: bool,
|
||||||
|
@ -644,32 +644,45 @@ async fn test_command(
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
let main_module = ModuleSpecifier::resolve_path("$deno$test.ts")?;
|
||||||
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 = tools::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(), permissions);
|
|
||||||
// Create a dummy source file.
|
// Create a dummy source file.
|
||||||
let source_file = File {
|
let source_file = File {
|
||||||
local: test_file_url.to_file_path().unwrap(),
|
local: main_module.as_url().to_file_path().unwrap(),
|
||||||
maybe_types: None,
|
maybe_types: None,
|
||||||
media_type: MediaType::TypeScript,
|
media_type: MediaType::TypeScript,
|
||||||
source: test_file.clone(),
|
source: tools::test_runner::render_test_file(
|
||||||
specifier: ModuleSpecifier::from(test_file_url.clone()),
|
test_modules.clone(),
|
||||||
|
fail_fast,
|
||||||
|
quiet,
|
||||||
|
filter,
|
||||||
|
),
|
||||||
|
specifier: main_module.clone(),
|
||||||
};
|
};
|
||||||
// Save our fake file into file fetcher cache
|
// Save our fake file into file fetcher cache
|
||||||
// to allow module access by TS compiler
|
// to allow module access by TS compiler
|
||||||
program_state.file_fetcher.insert_cached(source_file);
|
program_state.file_fetcher.insert_cached(source_file);
|
||||||
|
|
||||||
|
if no_run {
|
||||||
|
let lib = if flags.unstable {
|
||||||
|
module_graph::TypeLib::UnstableDenoWindow
|
||||||
|
} else {
|
||||||
|
module_graph::TypeLib::DenoWindow
|
||||||
|
};
|
||||||
|
program_state
|
||||||
|
.prepare_module_load(
|
||||||
|
main_module.clone(),
|
||||||
|
lib,
|
||||||
|
Permissions::allow_all(),
|
||||||
|
false,
|
||||||
|
program_state.maybe_import_map.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut worker =
|
||||||
|
MainWorker::new(&program_state, main_module.clone(), permissions);
|
||||||
|
|
||||||
let mut maybe_coverage_collector = if flags.coverage {
|
let mut maybe_coverage_collector = if flags.coverage {
|
||||||
let session = worker.create_inspector_session();
|
let session = worker.create_inspector_session();
|
||||||
let mut coverage_collector =
|
let mut coverage_collector =
|
||||||
|
@ -694,7 +707,7 @@ async fn test_command(
|
||||||
|
|
||||||
let filtered_coverages = tools::coverage::filter_script_coverages(
|
let filtered_coverages = tools::coverage::filter_script_coverages(
|
||||||
coverages,
|
coverages,
|
||||||
test_file_url,
|
main_module.as_url().clone(),
|
||||||
test_modules,
|
test_modules,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -815,13 +828,16 @@ pub fn main() {
|
||||||
DenoSubcommand::Repl => run_repl(flags).boxed_local(),
|
DenoSubcommand::Repl => run_repl(flags).boxed_local(),
|
||||||
DenoSubcommand::Run { script } => run_command(flags, script).boxed_local(),
|
DenoSubcommand::Run { script } => run_command(flags, script).boxed_local(),
|
||||||
DenoSubcommand::Test {
|
DenoSubcommand::Test {
|
||||||
|
no_run,
|
||||||
fail_fast,
|
fail_fast,
|
||||||
quiet,
|
quiet,
|
||||||
include,
|
include,
|
||||||
allow_none,
|
allow_none,
|
||||||
filter,
|
filter,
|
||||||
} => test_command(flags, include, fail_fast, quiet, allow_none, filter)
|
} => {
|
||||||
.boxed_local(),
|
test_command(flags, include, no_run, fail_fast, quiet, allow_none, filter)
|
||||||
|
.boxed_local()
|
||||||
|
}
|
||||||
DenoSubcommand::Completions { buf } => {
|
DenoSubcommand::Completions { buf } => {
|
||||||
if let Err(e) = write_to_stdout_ignore_sigpipe(&buf) {
|
if let Err(e) = write_to_stdout_ignore_sigpipe(&buf) {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
|
|
@ -294,46 +294,38 @@ fn serialize_worker_event(event: WorkerEvent) -> Value {
|
||||||
match event {
|
match event {
|
||||||
WorkerEvent::Message(buf) => json!({ "type": "msg", "data": buf }),
|
WorkerEvent::Message(buf) => json!({ "type": "msg", "data": buf }),
|
||||||
WorkerEvent::TerminalError(error) => match error.downcast::<JsError>() {
|
WorkerEvent::TerminalError(error) => match error.downcast::<JsError>() {
|
||||||
Ok(js_error) => {
|
Ok(js_error) => json!({
|
||||||
json!({
|
"type": "terminalError",
|
||||||
"type": "terminalError",
|
"error": {
|
||||||
"error": {
|
"message": js_error.message,
|
||||||
"message": js_error.message,
|
"fileName": js_error.script_resource_name,
|
||||||
"fileName": js_error.script_resource_name,
|
"lineNumber": js_error.line_number,
|
||||||
"lineNumber": js_error.line_number,
|
"columnNumber": js_error.start_column,
|
||||||
"columnNumber": js_error.start_column,
|
}
|
||||||
}
|
}),
|
||||||
})
|
Err(error) => json!({
|
||||||
}
|
"type": "terminalError",
|
||||||
Err(error) => {
|
"error": {
|
||||||
json!({
|
"message": error.to_string(),
|
||||||
"type": "terminalError",
|
}
|
||||||
"error": {
|
}),
|
||||||
"message": error.to_string(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
WorkerEvent::Error(error) => match error.downcast::<JsError>() {
|
WorkerEvent::Error(error) => match error.downcast::<JsError>() {
|
||||||
Ok(js_error) => {
|
Ok(js_error) => json!({
|
||||||
json!({
|
"type": "error",
|
||||||
"type": "error",
|
"error": {
|
||||||
"error": {
|
"message": js_error.message,
|
||||||
"message": js_error.message,
|
"fileName": js_error.script_resource_name,
|
||||||
"fileName": js_error.script_resource_name,
|
"lineNumber": js_error.line_number,
|
||||||
"lineNumber": js_error.line_number,
|
"columnNumber": js_error.start_column,
|
||||||
"columnNumber": js_error.start_column,
|
}
|
||||||
}
|
}),
|
||||||
})
|
Err(error) => json!({
|
||||||
}
|
"type": "error",
|
||||||
Err(error) => {
|
"error": {
|
||||||
json!({
|
"message": error.to_string(),
|
||||||
"type": "error",
|
}
|
||||||
"error": {
|
}),
|
||||||
"message": error.to_string(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
cli/tests/067_test_no_run_type_error.out
Normal file
4
cli/tests/067_test_no_run_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]
|
|
@ -2185,6 +2185,12 @@ fn _066_prompt() {
|
||||||
util::test_pty(args, output, input);
|
util::test_pty(args, output, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itest!(_067_test_no_run_type_error {
|
||||||
|
args: "test --unstable --no-run test_type_error",
|
||||||
|
output: "067_test_no_run_type_error.out",
|
||||||
|
exit_code: 1,
|
||||||
|
});
|
||||||
|
|
||||||
itest!(_073_worker_error {
|
itest!(_073_worker_error {
|
||||||
args: "run -A 073_worker_error.ts",
|
args: "run -A 073_worker_error.ts",
|
||||||
output: "073_worker_error.ts.out",
|
output: "073_worker_error.ts.out",
|
||||||
|
|
1
cli/tests/test_type_error/foo_test.ts
Normal file
1
cli/tests/test_type_error/foo_test.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
const a: string = 1;
|
|
@ -149,7 +149,7 @@ impl ModuleSpecifier {
|
||||||
/// Converts a string representing a relative or absolute path into a
|
/// Converts a string representing a relative or absolute path into a
|
||||||
/// ModuleSpecifier. A relative path is considered relative to the current
|
/// ModuleSpecifier. A relative path is considered relative to the current
|
||||||
/// working directory.
|
/// working directory.
|
||||||
fn resolve_path(
|
pub fn resolve_path(
|
||||||
path_str: &str,
|
path_str: &str,
|
||||||
) -> Result<ModuleSpecifier, ModuleResolutionError> {
|
) -> Result<ModuleSpecifier, ModuleResolutionError> {
|
||||||
let path = current_dir().unwrap().join(path_str);
|
let path = current_dir().unwrap().join(path_str);
|
||||||
|
|
Loading…
Reference in a new issue