From 7a9ebd15852eee7b676a671098d63bece679e0f7 Mon Sep 17 00:00:00 2001 From: Liam Murphy Date: Mon, 10 May 2021 16:06:13 +1000 Subject: feat: add deno test --watch (#9160) This commit implements file watching for deno test. When a file is changed, only the test modules which use it as a dependency are rerun. This is accomplished by reworking the file watching infrastructure to pass the paths which have changed to the resolver, and then constructing a module graph for each test module to check if it contains any changed files. --- cli/tools/fmt.rs | 44 +++++++++++++++++++++++++++++++++----------- cli/tools/test_runner.rs | 34 +++++++++++----------------------- 2 files changed, 44 insertions(+), 34 deletions(-) (limited to 'cli/tools') diff --git a/cli/tools/fmt.rs b/cli/tools/fmt.rs index 91d730c44..9a16afeca 100644 --- a/cli/tools/fmt.rs +++ b/cli/tools/fmt.rs @@ -10,12 +10,12 @@ use crate::colors; use crate::diff::diff; use crate::file_watcher; +use crate::file_watcher::ResolutionResult; use crate::fs_util::{collect_files, get_extension, is_supported_ext_fmt}; use crate::text_encoding; use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::futures; -use deno_core::futures::FutureExt; use log::debug; use log::info; use std::fs; @@ -37,15 +37,32 @@ pub async fn format( check: bool, watch: bool, ) -> Result<(), AnyError> { - let target_file_resolver = || { - // collect the files that are to be formatted - collect_files(&args, &ignore, is_supported_ext_fmt).and_then(|files| { - if files.is_empty() { - Err(generic_error("No target files found.")) + let resolver = |changed: Option>| { + let files_changed = changed.is_some(); + let result = + collect_files(&args, &ignore, is_supported_ext_fmt).map(|files| { + if let Some(paths) = changed { + files + .into_iter() + .filter(|path| paths.contains(path)) + .collect::>() + } else { + files + } + }); + let paths_to_watch = args.clone(); + async move { + if (files_changed || !watch) + && matches!(result, Ok(ref files) if files.is_empty()) + { + ResolutionResult::Ignore } else { - Ok(files) + ResolutionResult::Restart { + paths_to_watch, + result, + } } - }) + } }; let operation = |paths: Vec| { let config = get_typescript_config(); @@ -57,13 +74,18 @@ pub async fn format( } Ok(()) } - .boxed_local() }; if watch { - file_watcher::watch_func(target_file_resolver, operation, "Fmt").await?; + file_watcher::watch_func(resolver, operation, "Fmt").await?; } else { - operation(target_file_resolver()?).await?; + let files = + if let ResolutionResult::Restart { result, .. } = resolver(None).await { + result? + } else { + return Err(generic_error("No target files found.")); + }; + operation(files).await?; } Ok(()) diff --git a/cli/tools/test_runner.rs b/cli/tools/test_runner.rs index 7f3a139a4..e24d8b458 100644 --- a/cli/tools/test_runner.rs +++ b/cli/tools/test_runner.rs @@ -3,7 +3,6 @@ use crate::colors; use crate::create_main_worker; use crate::file_fetcher::File; -use crate::flags::Flags; use crate::fs_util; use crate::media_type::MediaType; use crate::module_graph; @@ -304,37 +303,30 @@ pub async fn run_test_file( Ok(()) } +/// Runs tests. +/// +/// Returns a boolean indicating whether the tests failed. #[allow(clippy::too_many_arguments)] pub async fn run_tests( - flags: Flags, - include: Option>, + program_state: Arc, + permissions: Permissions, + lib: module_graph::TypeLib, + test_modules: Vec, no_run: bool, fail_fast: bool, quiet: bool, allow_none: bool, filter: Option, concurrent_jobs: usize, -) -> Result<(), AnyError> { - let program_state = ProgramState::build(flags.clone()).await?; - let permissions = Permissions::from_options(&flags.clone().into()); - let cwd = std::env::current_dir().expect("No current directory"); - let include = include.unwrap_or_else(|| vec![".".to_string()]); - let test_modules = collect_test_module_specifiers(include, &cwd)?; - +) -> Result { if test_modules.is_empty() { println!("No matching test modules found"); if !allow_none { std::process::exit(1); } - return Ok(()); + return Ok(false); } - let lib = if flags.unstable { - module_graph::TypeLib::UnstableDenoWindow - } else { - module_graph::TypeLib::DenoWindow - }; - program_state .prepare_module_graph( test_modules.clone(), @@ -345,7 +337,7 @@ pub async fn run_tests( .await?; if no_run { - return Ok(()); + return Ok(false); } // Because scripts, and therefore worker.execute cannot detect unresolved promises at the moment @@ -475,11 +467,7 @@ pub async fn run_tests( if let Some(e) = join_errors.next() { Err(e) } else { - if result.unwrap_or(false) { - std::process::exit(1); - } - - Ok(()) + Ok(result.unwrap_or(false)) } } -- cgit v1.2.3