Skip to content

Commit 19bcb40

Browse files
authored
feat(cli/tools): add a subcommand --hide-stacktraces for test (#24095)
1 parent 4f49f70 commit 19bcb40

File tree

21 files changed

+300
-58
lines changed

21 files changed

+300
-58
lines changed

cli/args/flags.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ pub struct TestFlags {
403403
pub watch: Option<WatchFlagsWithPaths>,
404404
pub reporter: TestReporterConfig,
405405
pub junit_path: Option<String>,
406+
pub hide_stacktraces: bool,
406407
}
407408

408409
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -2999,6 +3000,12 @@ Directory arguments are expanded to all contained files matching the glob
29993000
.value_parser(["pretty", "dot", "junit", "tap"])
30003001
.help_heading(TEST_HEADING)
30013002
)
3003+
.arg(
3004+
Arg::new("hide-stacktraces")
3005+
.long("hide-stacktraces")
3006+
.help("Hide stack traces for errors in failure test results.")
3007+
.action(ArgAction::SetTrue)
3008+
)
30023009
.arg(env_file_arg())
30033010
)
30043011
}
@@ -4920,6 +4927,8 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) {
49204927
flags.log_level = Some(Level::Error);
49214928
}
49224929

4930+
let hide_stacktraces = matches.get_flag("hide-stacktraces");
4931+
49234932
flags.subcommand = DenoSubcommand::Test(TestFlags {
49244933
no_run,
49254934
doc,
@@ -4935,6 +4944,7 @@ fn test_parse(flags: &mut Flags, matches: &mut ArgMatches) {
49354944
watch: watch_arg_parse_with_paths(matches),
49364945
reporter,
49374946
junit_path,
4947+
hide_stacktraces,
49384948
});
49394949
}
49404950

@@ -9015,6 +9025,7 @@ mod tests {
90159025
watch: Default::default(),
90169026
reporter: Default::default(),
90179027
junit_path: None,
9028+
hide_stacktraces: false,
90189029
}),
90199030
unstable_config: UnstableConfig {
90209031
legacy_flag_enabled: true,
@@ -9102,6 +9113,7 @@ mod tests {
91029113
clean: false,
91039114
watch: Default::default(),
91049115
junit_path: None,
9116+
hide_stacktraces: false,
91059117
}),
91069118
type_check_mode: TypeCheckMode::Local,
91079119
permissions: PermissionFlags {
@@ -9140,6 +9152,7 @@ mod tests {
91409152
watch: Default::default(),
91419153
reporter: Default::default(),
91429154
junit_path: None,
9155+
hide_stacktraces: false,
91439156
}),
91449157
type_check_mode: TypeCheckMode::Local,
91459158
permissions: PermissionFlags {
@@ -9182,6 +9195,7 @@ mod tests {
91829195
watch: Default::default(),
91839196
reporter: Default::default(),
91849197
junit_path: None,
9198+
hide_stacktraces: false,
91859199
}),
91869200
permissions: PermissionFlags {
91879201
no_prompt: true,
@@ -9318,6 +9332,7 @@ mod tests {
93189332
watch: Default::default(),
93199333
reporter: Default::default(),
93209334
junit_path: None,
9335+
hide_stacktraces: false,
93219336
}),
93229337
permissions: PermissionFlags {
93239338
no_prompt: true,
@@ -9353,6 +9368,7 @@ mod tests {
93539368
watch: Some(Default::default()),
93549369
reporter: Default::default(),
93559370
junit_path: None,
9371+
hide_stacktraces: false,
93569372
}),
93579373
permissions: PermissionFlags {
93589374
no_prompt: true,
@@ -9387,6 +9403,7 @@ mod tests {
93879403
watch: Some(Default::default()),
93889404
reporter: Default::default(),
93899405
junit_path: None,
9406+
hide_stacktraces: false,
93909407
}),
93919408
permissions: PermissionFlags {
93929409
no_prompt: true,
@@ -9428,6 +9445,7 @@ mod tests {
94289445
}),
94299446
reporter: Default::default(),
94309447
junit_path: None,
9448+
hide_stacktraces: false,
94319449
}),
94329450
type_check_mode: TypeCheckMode::Local,
94339451
permissions: PermissionFlags {
@@ -9624,6 +9642,26 @@ mod tests {
96249642
);
96259643
}
96269644

9645+
#[test]
9646+
fn test_hide_stacktraces() {
9647+
let r = flags_from_vec(svec!["deno", "test", "--hide-stacktraces"]);
9648+
assert_eq!(
9649+
r.unwrap(),
9650+
Flags {
9651+
subcommand: DenoSubcommand::Test(TestFlags {
9652+
hide_stacktraces: true,
9653+
..TestFlags::default()
9654+
}),
9655+
type_check_mode: TypeCheckMode::Local,
9656+
permissions: PermissionFlags {
9657+
no_prompt: true,
9658+
..Default::default()
9659+
},
9660+
..Flags::default()
9661+
}
9662+
);
9663+
}
9664+
96279665
#[test]
96289666
fn bundle_with_cafile() {
96299667
let r = flags_from_vec(svec![

cli/args/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ pub struct WorkspaceTestOptions {
377377
pub trace_leaks: bool,
378378
pub reporter: TestReporterConfig,
379379
pub junit_path: Option<String>,
380+
pub hide_stacktraces: bool,
380381
}
381382

382383
impl WorkspaceTestOptions {
@@ -394,6 +395,7 @@ impl WorkspaceTestOptions {
394395
trace_leaks: test_flags.trace_leaks,
395396
reporter: test_flags.reporter,
396397
junit_path: test_flags.junit_path.clone(),
398+
hide_stacktraces: test_flags.hide_stacktraces,
397399
}
398400
}
399401
}

cli/lsp/testing/execution.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::lsp::logging::lsp_log;
1515
use crate::tools::test;
1616
use crate::tools::test::create_test_event_channel;
1717
use crate::tools::test::FailFastTracker;
18+
use crate::tools::test::TestFailureFormatOptions;
1819

1920
use deno_core::anyhow::anyhow;
2021
use deno_core::error::AnyError;
@@ -655,7 +656,10 @@ impl LspTestReporter {
655656
let desc = self.tests.get(&desc.id).unwrap();
656657
self.progress(lsp_custom::TestRunProgressMessage::Failed {
657658
test: desc.as_test_identifier(&self.tests),
658-
messages: as_test_messages(failure.to_string(), false),
659+
messages: as_test_messages(
660+
failure.format(&TestFailureFormatOptions::default()),
661+
false,
662+
),
659663
duration: Some(elapsed as u32),
660664
})
661665
}
@@ -675,7 +679,7 @@ impl LspTestReporter {
675679
let err_string = format!(
676680
"Uncaught error from {}: {}\nThis error was not caught from a test and caused the test runner to fail on the referenced module.\nIt most likely originated from a dangling promise, event/timeout handler or top-level code.",
677681
origin,
678-
test::fmt::format_test_error(js_error)
682+
test::fmt::format_test_error(js_error, &TestFailureFormatOptions::default())
679683
);
680684
let messages = as_test_messages(err_string, false);
681685
for desc in self.tests.values().filter(|d| d.origin() == origin) {
@@ -751,7 +755,10 @@ impl LspTestReporter {
751755
test::TestStepResult::Failed(failure) => {
752756
self.progress(lsp_custom::TestRunProgressMessage::Failed {
753757
test: desc.as_test_identifier(&self.tests),
754-
messages: as_test_messages(failure.to_string(), false),
758+
messages: as_test_messages(
759+
failure.format(&TestFailureFormatOptions::default()),
760+
false,
761+
),
755762
duration: Some(elapsed as u32),
756763
})
757764
}

cli/tools/bench/reporters.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use serde::Serialize;
44

5+
use crate::tools::test::TestFailureFormatOptions;
56
use crate::version;
67

78
use super::*;
@@ -243,7 +244,10 @@ impl BenchReporter for ConsoleReporter {
243244
&desc.name,
244245
&mitata::reporter::Error {
245246
stack: None,
246-
message: format_test_error(js_error),
247+
message: format_test_error(
248+
js_error,
249+
&TestFailureFormatOptions::default()
250+
),
247251
},
248252
options
249253
)
@@ -298,7 +302,7 @@ impl BenchReporter for ConsoleReporter {
298302
println!(
299303
"{}: {}",
300304
colors::red_bold("error"),
301-
format_test_error(&error)
305+
format_test_error(&error, &TestFailureFormatOptions::default())
302306
);
303307
println!("This error was not caught from a benchmark and caused the bench runner to fail on the referenced module.");
304308
println!("It most likely originated from a dangling promise, event/timeout handler or top-level code.");

cli/tools/jupyter/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::tools::repl;
1111
use crate::tools::test::create_single_test_event_channel;
1212
use crate::tools::test::reporters::PrettyTestReporter;
1313
use crate::tools::test::TestEventWorkerSender;
14+
use crate::tools::test::TestFailureFormatOptions;
1415
use crate::CliFactory;
1516
use deno_core::anyhow::bail;
1617
use deno_core::anyhow::Context;
@@ -142,8 +143,15 @@ pub async fn kernel(
142143
})?;
143144
repl_session.set_test_reporter_factory(Box::new(move || {
144145
Box::new(
145-
PrettyTestReporter::new(false, true, false, true, cwd_url.clone())
146-
.with_writer(Box::new(TestWriter(stdio_tx.clone()))),
146+
PrettyTestReporter::new(
147+
false,
148+
true,
149+
false,
150+
true,
151+
cwd_url.clone(),
152+
TestFailureFormatOptions::default(),
153+
)
154+
.with_writer(Box::new(TestWriter(stdio_tx.clone()))),
147155
)
148156
}));
149157

cli/tools/repl/session.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::tools::test::send_test_event;
1616
use crate::tools::test::worker_has_tests;
1717
use crate::tools::test::TestEvent;
1818
use crate::tools::test::TestEventReceiver;
19+
use crate::tools::test::TestFailureFormatOptions;
1920

2021
use deno_ast::diagnostics::Diagnostic;
2122
use deno_ast::swc::ast as swc_ast;
@@ -276,6 +277,7 @@ impl ReplSession {
276277
false,
277278
true,
278279
cwd_url.clone(),
280+
TestFailureFormatOptions::default(),
279281
))
280282
}),
281283
main_module,

cli/tools/test/fmt.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,24 @@ fn abbreviate_test_error(js_error: &JsError) -> JsError {
7272
// This function prettifies `JsError` and applies some changes specifically for
7373
// test runner purposes:
7474
//
75+
// - hide stack traces if `options.hide_stacktraces` is set to `true`
76+
//
7577
// - filter out stack frames:
7678
// - if stack trace consists of mixed user and internal code, the frames
7779
// below the first user code frame are filtered out
7880
// - if stack trace consists only of internal code it is preserved as is
79-
pub fn format_test_error(js_error: &JsError) -> String {
81+
pub fn format_test_error(
82+
js_error: &JsError,
83+
options: &TestFailureFormatOptions,
84+
) -> String {
8085
let mut js_error = abbreviate_test_error(js_error);
8186
js_error.exception_message = js_error
8287
.exception_message
8388
.trim_start_matches("Uncaught ")
8489
.to_string();
90+
if options.hide_stacktraces {
91+
return js_error.exception_message;
92+
}
8593
format_js_error(&js_error)
8694
}
8795

0 commit comments

Comments
 (0)