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":

<img width="713" alt="image"
src="https://github.com/user-attachments/assets/e8bb1cb1-f0a5-4eb1-b9a6-7188a9fa47ae"
/>

I can't run dynamic tests:

<img width="703" alt="image"
src="https://github.com/user-attachments/assets/d7eef1bc-e99a-4f05-9d62-ec49b8194959"
/>

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:

<img width="772" alt="image"
src="https://github.com/user-attachments/assets/db3a6fe0-ad90-4853-8e98-4215e41dfe88"
/>

Release Notes:

- Allow to run dynamic TypeScript/JavaScript tests

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
This commit is contained in:
Alexander 2025-06-09 17:13:25 +07:00 committed by GitHub
parent 79e7ccc1fe
commit 6fe58a2c4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 106 additions and 5 deletions

View file

@ -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

View file

@ -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)
)

View file

@ -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<HashMap<String, String>>,
_toolchains: Arc<dyn LanguageToolchainStore>,
cx: &mut App,
) -> Task<Result<task::TaskVariables>> {
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<OsString> {
]
}
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,
}

View file

@ -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

View file

@ -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)
)