#![allow(deprecated)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use tempfile::tempdir;
fn fixture_path(name: &str) -> std::path::PathBuf {
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join(name)
}
#[test]
fn test_help() {
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains(
"Automatically update Markdown files",
));
}
#[test]
fn test_version() {
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg("--version")
.assert()
.success()
.stdout(predicate::str::contains("markdown-code-runner"));
}
#[test]
fn test_missing_input() {
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.assert()
.failure()
.stderr(predicate::str::contains("required"));
}
#[test]
fn test_nonexistent_file() {
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg("/nonexistent/file.md").assert().failure();
}
#[test]
fn test_process_fixture() {
let dir = tempdir().unwrap();
let output_path = dir.path().join("output.md");
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(fixture_path("test_main_app.md"))
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
let expected = fs::read_to_string(fixture_path("test_main_app_expected_output.md")).unwrap();
assert_eq!(output, expected);
}
#[test]
fn test_simple_python_block() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```python markdown-code-runner
print('Hello, world!')
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("Hello, world!"));
assert!(!output.contains("old output"));
}
#[test]
fn test_simple_bash_block() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```bash markdown-code-runner
echo "Hello from bash"
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("Hello from bash"));
assert!(!output.contains("old output"));
}
#[test]
fn test_skip_marker() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
<!-- CODE:SKIP -->
```python markdown-code-runner
print('EXECUTED_OUTPUT')
```
<!-- OUTPUT:START -->
original output preserved
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("original output preserved"));
assert!(!output.contains("\nEXECUTED_OUTPUT\n"));
}
#[test]
fn test_no_execute() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```python markdown-code-runner
print('Hello')
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-execute")
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("old output"));
}
#[test]
fn test_standardize_flag() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```python markdown-code-runner
print('Hello')
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("```python\n"));
assert!(!output.contains("```python markdown-code-runner"));
}
#[test]
fn test_hidden_python_code() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
<!-- CODE:START -->
<!-- print('Hidden hello!') -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("Hidden hello!"));
assert!(!output.contains("old output"));
}
#[test]
fn test_hidden_bash_code() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
<!-- CODE:BASH:START -->
<!-- echo "Hidden bash!" -->
<!-- CODE:END -->
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains("Hidden bash!"));
assert!(!output.contains("old output"));
}
#[test]
fn test_variable_persistence() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```python markdown-code-runner
a = 42
print(a)
```
<!-- OUTPUT:START -->
<!-- OUTPUT:END -->
Second block uses the variable:
```python markdown-code-runner
print(a)
```
<!-- OUTPUT:START -->
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
let output_sections: Vec<&str> = output.split("<!-- OUTPUT:START -->").skip(1).collect();
assert_eq!(output_sections.len(), 2);
for section in output_sections {
let end_idx = section.find("<!-- OUTPUT:END -->").unwrap();
let section_content = §ion[..end_idx];
assert!(
section_content.contains("42"),
"Output section should contain 42: {}",
section_content
);
}
}
#[test]
fn test_indented_code_block() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"1. List item:
```python markdown-code-runner
print('indented')
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let output = fs::read_to_string(&output_path).unwrap();
assert!(output.contains(" indented")); assert!(!output.contains("old output"));
}
#[test]
fn test_verbose_mode() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let input = r#"# Test
```python markdown-code-runner
print('Hello')
```
<!-- OUTPUT:START -->
<!-- OUTPUT:END -->
"#;
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--verbose")
.assert()
.success()
.stderr(predicate::str::contains("Processing input file"))
.stderr(predicate::str::contains("Writing output to"))
.stderr(predicate::str::contains("Done!"));
}
#[test]
fn test_write_to_file() {
let dir = tempdir().unwrap();
let input_path = dir.path().join("input.md");
let output_path = dir.path().join("output.md");
let code_file = dir.path().join("test.py");
let input = format!(
r#"# Test
```python markdown-code-runner filename={}
print('Hello')
```
<!-- OUTPUT:START -->
old output
<!-- OUTPUT:END -->
"#,
code_file.display()
);
fs::write(&input_path, input).unwrap();
let mut cmd = Command::cargo_bin("markdown-code-runner").unwrap();
cmd.arg(&input_path)
.arg("-o")
.arg(&output_path)
.arg("--no-backtick-standardize")
.assert()
.success();
let code_content = fs::read_to_string(&code_file).unwrap();
assert_eq!(code_content, "print('Hello')");
let output = fs::read_to_string(&output_path).unwrap();
assert!(!output.contains("old output"));
}