fix(cli): make --quiet suppress JS console errors on stderr (#56) (#74)

* fix(cli): make --quiet suppress JS console errors on stderr (#56)

The --quiet flag was only gating banner prints in run_fetch but not
the global tracing_subscriber, so ERROR-level JS console output kept
leaking to stderr.

Detect quiet from the parsed Fetch subcommand before initializing
the subscriber and switch the filter to "off" in that case. Verbose
still wins over quiet to keep diagnostic mode usable.

Generated by Ora Studio
Vibe coded by ousamabenyounes

Co-Authored-By: Ora Studio <noreply@oratelecom.net>

* test(cli): add integration tests for --quiet matcher wiring

Address review feedback on PR #74: previous tests only covered the
pure helper select_log_filter, not the matches!() wiring in main()
that maps Command::Fetch { quiet: true, .. } → quiet flag.

Extract the matcher into is_quiet_command(&Option<Command>) and add
six new tests that parse real CLI args via Args::try_parse_from and
assert the full chain:

- parsed_fetch_with_quiet_flag_is_detected: --quiet on fetch → true
- parsed_fetch_without_quiet_is_not_detected: bare fetch → false
- parsed_serve_command_is_not_quiet: serve subcommand → false
- no_subcommand_is_not_quiet: None → false
- parsed_fetch_quiet_resolves_to_off_filter: end-to-end clap → "off"
- matcher_still_uses_fetch_variant: regression guard if Command::Fetch
  variant is renamed/restructured

cargo test -p obscura-cli: 10 passed; 0 failed.

Co-Authored-By: Ora Studio <noreply@oratelecom.net>

---------

Co-authored-by: Ora Studio <noreply@oratelecom.net>
This commit is contained in:
Ben YounesandOra Studio authored and GitHub committed 2026-05-09 17:27:03 +02:00
1 parent e60da1af39
commit 84115ca06e
1 file changed
+102 -1
+102 -1
View File
@@ -119,11 +119,26 @@ fn print_banner(port: u16) {
"#, port);
}
fn select_log_filter(verbose: bool, quiet: bool) -> &'static str {
if verbose {
"debug"
} else if quiet {
"off"
} else {
"warn"
}
}
fn is_quiet_command(cmd: &Option<Command>) -> bool {
matches!(cmd, Some(Command::Fetch { quiet: true, .. }))
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let args = Args::parse();
let filter = if args.verbose { "debug" } else { "warn" };
let quiet = is_quiet_command(&args.command);
let filter = select_log_filter(args.verbose, quiet);
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
@@ -725,3 +740,89 @@ fn dump_links(page: &Page) {
}
});
}
#[cfg(test)]
mod tests {
use super::{is_quiet_command, select_log_filter, Args, Command};
use clap::Parser;
#[test]
fn default_filter_is_warn() {
assert_eq!(select_log_filter(false, false), "warn");
}
#[test]
fn verbose_filter_is_debug() {
assert_eq!(select_log_filter(true, false), "debug");
}
#[test]
fn quiet_filter_is_off() {
assert_eq!(select_log_filter(false, true), "off");
}
#[test]
fn verbose_wins_over_quiet() {
assert_eq!(select_log_filter(true, true), "debug");
}
#[test]
fn parsed_fetch_with_quiet_flag_is_detected() {
let args = Args::try_parse_from([
"obscura",
"fetch",
"--quiet",
"https://example.com",
])
.expect("clap should accept --quiet on fetch");
assert!(is_quiet_command(&args.command));
}
#[test]
fn parsed_fetch_without_quiet_is_not_detected() {
let args = Args::try_parse_from(["obscura", "fetch", "https://example.com"])
.expect("clap should accept fetch without --quiet");
assert!(!is_quiet_command(&args.command));
}
#[test]
fn parsed_serve_command_is_not_quiet() {
let args = Args::try_parse_from(["obscura", "serve"])
.expect("clap should accept serve");
assert!(!is_quiet_command(&args.command));
}
#[test]
fn no_subcommand_is_not_quiet() {
assert!(!is_quiet_command(&None));
}
#[test]
fn parsed_fetch_quiet_resolves_to_off_filter() {
let args = Args::try_parse_from([
"obscura",
"fetch",
"--quiet",
"https://example.com",
])
.unwrap();
let filter = select_log_filter(args.verbose, is_quiet_command(&args.command));
assert_eq!(filter, "off");
}
#[test]
fn matcher_still_uses_fetch_variant() {
let cmd = Some(Command::Fetch {
url: "https://x".to_string(),
dump: super::DumpFormat::Html,
selector: None,
wait: 5,
timeout: 30,
wait_until: "load".to_string(),
user_agent: None,
stealth: false,
eval: None,
quiet: true,
});
assert!(is_quiet_command(&cmd));
}
}