@@ -88,17 +88,32 @@ fn build_test_script(test_patch: &str, fail_to_pass: Option<&str>) -> String {
8888 if !tests. is_empty ( ) {
8989 script. push_str ( "# Run fail-to-pass tests\n " ) ;
9090 for test in & tests {
91- script. push_str ( & format ! ( "python -m pytest {} -x\n " , test) ) ;
91+ if is_full_command ( test) {
92+ // Entry is a complete command (e.g. "npx playwright test ...")
93+ script. push_str ( & format ! ( "{}\n " , test) ) ;
94+ } else {
95+ // Entry is a pytest path
96+ script. push_str ( & format ! ( "python3 -m pytest {} -x\n " , test) ) ;
97+ }
9298 }
9399 }
94100 } else if !test_patch. is_empty ( ) {
95101 script. push_str ( "# Run test suite\n " ) ;
96- script. push_str ( "python -m pytest -x\n " ) ;
102+ script. push_str ( "python3 -m pytest -x\n " ) ;
97103 }
98104
99105 script
100106}
101107
108+ fn is_full_command ( test : & str ) -> bool {
109+ let cmd_prefixes = [
110+ "npx " , "npm " , "node " , "yarn " , "pnpm " , "python " , "python3 " , "pytest " , "cargo " ,
111+ "make " , "go " , "mvn " , "gradle " , "dotnet " , "ruby " , "bundle " , "sh " , "bash " , "./" ,
112+ ] ;
113+ let t = test. trim ( ) ;
114+ cmd_prefixes. iter ( ) . any ( |p| t. starts_with ( p) )
115+ }
116+
102117fn parse_test_list ( raw : & str ) -> Vec < String > {
103118 let trimmed = raw. trim ( ) ;
104119 if trimmed. is_empty ( ) {
@@ -116,8 +131,33 @@ fn parse_test_list(raw: &str) -> Vec<String> {
116131 . collect ( )
117132}
118133
134+ fn auto_install_commands ( language : & str ) -> Option < Vec < String > > {
135+ match language {
136+ "python" => Some ( vec ! [
137+ "pip install -e '.[dev,test]' 2>/dev/null || pip install -e . 2>/dev/null || true" . to_string( ) ,
138+ "pip install pytest 2>/dev/null || true" . to_string( ) ,
139+ ] ) ,
140+ "javascript" | "typescript" => Some ( vec ! [
141+ "npm install --legacy-peer-deps 2>/dev/null || yarn install --frozen-lockfile 2>/dev/null || true" . to_string( ) ,
142+ ] ) ,
143+ "go" => Some ( vec ! [
144+ "go mod download 2>/dev/null || true" . to_string( ) ,
145+ ] ) ,
146+ "rust" => Some ( vec ! [
147+ "cargo fetch 2>/dev/null || true" . to_string( ) ,
148+ ] ) ,
149+ _ => Some ( vec ! [
150+ "pip install -e . 2>/dev/null || npm install 2>/dev/null || true" . to_string( ) ,
151+ ] ) ,
152+ }
153+ }
154+
119155fn convert_dataset_entry_to_task ( entry : & DatasetEntry ) -> Result < SweForgeTask > {
120156 let repo_url = build_repo_url ( & entry. repo ) ;
157+ let language = entry
158+ . language
159+ . clone ( )
160+ . unwrap_or_else ( || "python" . to_string ( ) ) ;
121161
122162 let f2p: Option < Vec < String > > = entry
123163 . fail_to_pass
@@ -128,12 +168,14 @@ fn convert_dataset_entry_to_task(entry: &DatasetEntry) -> Result<SweForgeTask> {
128168 . as_deref ( )
129169 . and_then ( |s| serde_json:: from_str ( s) . ok ( ) ) ;
130170
171+ let install = auto_install_commands ( & language) ;
172+
131173 let workspace = WorkspaceConfig {
132174 repo : repo_url,
133175 version : entry. version . clone ( ) . unwrap_or_default ( ) ,
134176 base_commit : Some ( entry. base_commit . clone ( ) ) ,
135- install : None ,
136- language : Some ( "python" . to_string ( ) ) ,
177+ install,
178+ language : Some ( language ) ,
137179 fail_to_pass : f2p,
138180 pass_to_pass : p2p,
139181 install_config : None ,
@@ -311,7 +353,7 @@ mod tests {
311353 let script = build_test_script ( "diff --git a/t.py b/t.py" , None ) ;
312354 assert ! ( script. contains( "git apply" ) ) ;
313355 assert ! ( script. contains( "diff --git a/t.py b/t.py" ) ) ;
314- assert ! ( script. contains( "python -m pytest -x" ) ) ;
356+ assert ! ( script. contains( "python3 -m pytest -x" ) ) ;
315357 }
316358
317359 #[ test]
@@ -321,7 +363,7 @@ mod tests {
321363 Some ( r#"["tests/test_orm.py::test_query"]"# ) ,
322364 ) ;
323365 assert ! ( script. contains( "git apply" ) ) ;
324- assert ! ( script. contains( "python -m pytest tests/test_orm.py::test_query -x" ) ) ;
366+ assert ! ( script. contains( "python3 -m pytest tests/test_orm.py::test_query -x" ) ) ;
325367 }
326368
327369 #[ test]
0 commit comments