use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
fn binary() -> PathBuf {
if let Ok(p) = std::env::var("CARGO_BIN_EXE_markdown-reader") {
return p.into();
}
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("target")
.join("debug")
.join("markdown-reader")
}
const FIXTURE: &str = "\
# Title
## Foo
body1
## Bar
body2
";
#[test]
fn extracts_first_matching_section_foo() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("doc.md");
fs::write(&path, FIXTURE).unwrap();
let output = Command::new(binary())
.args(["--section", "Foo", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert!(
output.status.success(),
"exit should be 0 for a found section; got {}\nstderr: {}",
output.status,
String::from_utf8_lossy(&output.stderr),
);
let stdout = String::from_utf8(output.stdout).expect("stdout is not valid UTF-8");
assert!(
stdout.starts_with("## Foo"),
"output should start with '## Foo', got: {stdout:?}"
);
assert!(
stdout.contains("body1"),
"output should contain 'body1', got: {stdout:?}"
);
assert!(
!stdout.contains("## Bar"),
"output must not include the next heading '## Bar', got: {stdout:?}"
);
}
#[test]
fn extracts_first_matching_section_bar() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("doc.md");
fs::write(&path, FIXTURE).unwrap();
let output = Command::new(binary())
.args(["--section", "Bar", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert!(
output.status.success(),
"exit should be 0 for a found section; got {}",
output.status,
);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.starts_with("## Bar"), "expected '## Bar' heading");
assert!(stdout.contains("body2"), "expected 'body2' in output");
}
#[test]
fn case_insensitive_match_succeeds() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("ci.md");
fs::write(&path, "# Features Overview\n\nsome content\n").unwrap();
let output = Command::new(binary())
.args(["--section", "features", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert!(
output.status.success(),
"case-insensitive match should succeed; exit={}\nstderr: {}",
output.status,
String::from_utf8_lossy(&output.stderr),
);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(
stdout.contains("Features Overview"),
"expected heading in output, got: {stdout:?}"
);
}
#[test]
fn stops_at_higher_level_heading() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("doc.md");
fs::write(&path, "# Top\n\n## Sub\nbody\n\n# Other\n").unwrap();
let output = Command::new(binary())
.args(["--section", "Sub", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert!(output.status.success(), "expected exit 0");
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stdout.contains("body"), "expected body text");
assert!(
!stdout.contains("# Other"),
"should not include the terminating heading"
);
}
#[test]
fn last_section_extends_to_eof() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("doc.md");
fs::write(&path, "# Intro\n\nbody\n\n# Appendix\n\nappendix body\n").unwrap();
let output = Command::new(binary())
.args(["--section", "Appendix", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert!(output.status.success(), "expected exit 0");
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(
stdout.contains("appendix body"),
"last section should include all remaining content"
);
}
#[test]
fn no_match_exits_one() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("doc.md");
fs::write(&path, FIXTURE).unwrap();
let output = Command::new(binary())
.args(["--section", "DoesNotExist", path.to_str().unwrap()])
.output()
.expect("failed to run binary");
assert_eq!(
output.status.code(),
Some(1),
"expected exit code 1 for no-match; stdout={}",
String::from_utf8_lossy(&output.stdout),
);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(
stdout.is_empty(),
"stdout must be empty on no-match, got: {stdout:?}"
);
}