From 6fe58a2c4ee71db16a68b3ad79824929f76a74fc Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 9 Jun 2025 17:13:25 +0700 Subject: [PATCH] Allow to run dynamic TypeScript and JavaScript tests (#31499) First of all thank you for such a fast editor! I realized that the existing support for detecting runnable test cases for typescript/javascript is not full. Meanwhile I can run most of test by pressing "run button": image I can't run dynamic tests: image I was curious whether I can improve it on my own and created this pr. I edited schemas and added minor changes in `TaskTemplate` to allow to replace '%s' with regexp pattern, so it can match test cases: image Release Notes: - Allow to run dynamic TypeScript/JavaScript tests --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> --- crates/languages/src/javascript/outline.scm | 17 ++++++++ crates/languages/src/javascript/runnables.scm | 19 +++++++++ crates/languages/src/typescript.rs | 39 ++++++++++++++++--- crates/languages/src/typescript/outline.scm | 17 ++++++++ crates/languages/src/typescript/runnables.scm | 19 +++++++++ 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/crates/languages/src/javascript/outline.scm b/crates/languages/src/javascript/outline.scm index d70d8bb597..f00518a277 100644 --- a/crates/languages/src/javascript/outline.scm +++ b/crates/languages/src/javascript/outline.scm @@ -80,4 +80,21 @@ ) ) @item +; Add support for parameterized tests +( + (call_expression + function: (call_expression + function: (member_expression + object: [(identifier) @_name (member_expression object: (identifier) @_name)] + property: (property_identifier) @_property + ) + (#any-of? @_name "it" "test" "describe" "context" "suite") + (#eq? @_property "each") + ) + arguments: ( + arguments . (string (string_fragment) @name) + ) + ) +) @item + (comment) @annotation diff --git a/crates/languages/src/javascript/runnables.scm b/crates/languages/src/javascript/runnables.scm index 1b68b9a41e..e953632f9a 100644 --- a/crates/languages/src/javascript/runnables.scm +++ b/crates/languages/src/javascript/runnables.scm @@ -19,3 +19,22 @@ (#set! tag js-test) ) + +; Add support for parameterized tests +( + (call_expression + function: (call_expression + function: (member_expression + object: [(identifier) @_name (member_expression object: (identifier) @_name)] + property: (property_identifier) @_property + ) + (#any-of? @_name "it" "test" "describe" "context" "suite") + (#eq? @_property "each") + ) + arguments: ( + arguments . (string (string_fragment) @run) + ) + ) @_js-test + + (#set! tag js-test) +) diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index 2ed082ee24..0662eddd3f 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -34,11 +34,15 @@ const TYPESCRIPT_RUNNER_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("TYPESCRIPT_RUNNER")); const TYPESCRIPT_JEST_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("TYPESCRIPT_JEST")); +const TYPESCRIPT_JEST_TEST_NAME_VARIABLE: VariableName = + VariableName::Custom(Cow::Borrowed("TYPESCRIPT_JEST_TEST_NAME")); const TYPESCRIPT_MOCHA_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("TYPESCRIPT_MOCHA")); const TYPESCRIPT_VITEST_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("TYPESCRIPT_VITEST")); +const TYPESCRIPT_VITEST_TEST_NAME_VARIABLE: VariableName = + VariableName::Custom(Cow::Borrowed("TYPESCRIPT_VITEST_TEST_NAME")); const TYPESCRIPT_JASMINE_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("TYPESCRIPT_JASMINE")); const TYPESCRIPT_BUILD_SCRIPT_TASK_VARIABLE: VariableName = @@ -183,7 +187,10 @@ impl ContextProvider for TypeScriptContextProvider { args: vec![ TYPESCRIPT_JEST_TASK_VARIABLE.template_value(), "--testNamePattern".to_owned(), - format!("\"{}\"", VariableName::Symbol.template_value()), + format!( + "\"{}\"", + TYPESCRIPT_JEST_TEST_NAME_VARIABLE.template_value() + ), VariableName::RelativeFile.template_value(), ], tags: vec![ @@ -221,7 +228,7 @@ impl ContextProvider for TypeScriptContextProvider { TYPESCRIPT_VITEST_TASK_VARIABLE.template_value(), "run".to_owned(), "--testNamePattern".to_owned(), - format!("\"{}\"", VariableName::Symbol.template_value()), + format!("\"{}\"", TYPESCRIPT_VITEST_TASK_VARIABLE.template_value()), VariableName::RelativeFile.template_value(), ], tags: vec![ @@ -344,14 +351,27 @@ impl ContextProvider for TypeScriptContextProvider { fn build_context( &self, - _variables: &task::TaskVariables, + current_vars: &task::TaskVariables, location: ContextLocation<'_>, _project_env: Option>, _toolchains: Arc, cx: &mut App, ) -> Task> { + let mut vars = task::TaskVariables::default(); + + if let Some(symbol) = current_vars.get(&VariableName::Symbol) { + vars.insert( + TYPESCRIPT_JEST_TEST_NAME_VARIABLE, + replace_test_name_parameters(symbol), + ); + vars.insert( + TYPESCRIPT_VITEST_TEST_NAME_VARIABLE, + replace_test_name_parameters(symbol), + ); + } + let Some((fs, worktree_root)) = location.fs.zip(location.worktree_root) else { - return Task::ready(Ok(task::TaskVariables::default())); + return Task::ready(Ok(vars)); }; let package_json_contents = self.last_package_json.clone(); @@ -361,7 +381,10 @@ impl ContextProvider for TypeScriptContextProvider { .context("package.json context retrieval") .log_err() .unwrap_or_else(task::TaskVariables::default); - Ok(variables) + + vars.extend(variables); + + Ok(vars) }) } } @@ -426,6 +449,12 @@ fn eslint_server_binary_arguments(server_path: &Path) -> Vec { ] } +fn replace_test_name_parameters(test_name: &str) -> String { + let pattern = regex::Regex::new(r"(%|\$)[0-9a-zA-Z]+").unwrap(); + + pattern.replace_all(test_name, "(.+?)").to_string() +} + pub struct TypeScriptLspAdapter { node: NodeRuntime, } diff --git a/crates/languages/src/typescript/outline.scm b/crates/languages/src/typescript/outline.scm index c0c5c735e2..a2503bd403 100644 --- a/crates/languages/src/typescript/outline.scm +++ b/crates/languages/src/typescript/outline.scm @@ -88,4 +88,21 @@ ) ) @item +; Add support for parameterized tests +( + (call_expression + function: (call_expression + function: (member_expression + object: [(identifier) @_name (member_expression object: (identifier) @_name)] + property: (property_identifier) @_property + ) + (#any-of? @_name "it" "test" "describe" "context" "suite") + (#any-of? @_property "each") + ) + arguments: ( + arguments . (string (string_fragment) @name) + ) + ) +) @item + (comment) @annotation diff --git a/crates/languages/src/typescript/runnables.scm b/crates/languages/src/typescript/runnables.scm index 1b68b9a41e..ce6da8f903 100644 --- a/crates/languages/src/typescript/runnables.scm +++ b/crates/languages/src/typescript/runnables.scm @@ -19,3 +19,22 @@ (#set! tag js-test) ) + +; Add support for parameterized tests +( + (call_expression + function: (call_expression + function: (member_expression + object: [(identifier) @_name (member_expression object: (identifier) @_name)] + property: (property_identifier) @_property + ) + (#any-of? @_name "it" "test" "describe" "context" "suite") + (#any-of? @_property "each") + ) + arguments: ( + arguments . (string (string_fragment) @run) + ) + ) @_js-test + + (#set! tag js-test) +)