use indoc::indoc;
use liwe::model::config::{Configuration, LibraryOptions, MarkdownOptions};
use std::fs::{create_dir_all, read_to_string, write};
use std::process::Command;
use tempfile::TempDir;
#[test]
fn test_inline_list_references() {
let temp_dir = setup_workspace_with_docs(vec
[Database](db)
"},
),
("arch", "# Architecture"),
("db", "# Database"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--list"]);
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert_eq!(
stdout,
indoc! {"
1: [Architecture](arch)
2: [Database](db)
"}
);
}
#[test]
fn test_inline_by_reference() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
(
"arch",
indoc! {"
# Architecture
Architecture content here.
"},
),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "arch"]);
assert!(output.status.success());
assert!(
!temp_path.join("arch.md").exists(),
"Target file should be deleted"
);
let index_content = read_to_string(temp_path.join("index.md")).unwrap();
assert_eq!(
index_content,
indoc! {"
# Index
## Architecture
Architecture content here.
"}
);
}
#[test]
fn test_inline_by_block_number() {
let temp_dir = setup_workspace_with_docs(vec
[Second](second)
"},
),
("first", "# First\n\nFirst content"),
("second", "# Second\n\nSecond content"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--block", "1"]);
assert!(output.status.success());
assert!(
!temp_path.join("first.md").exists(),
"First file should be deleted"
);
assert!(
temp_path.join("second.md").exists(),
"Second file should remain"
);
let index_content = read_to_string(temp_path.join("index.md")).unwrap();
assert_eq!(
index_content,
indoc! {"
# Index
[Second](second)
## First
First content
"}
);
}
#[test]
fn test_inline_keep_target() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
(
"arch",
indoc! {"
# Architecture
Architecture content.
"},
),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(
temp_path,
&["index", "--reference", "arch", "--keep-target"],
);
assert!(output.status.success());
assert!(
temp_path.join("arch.md").exists(),
"Target file should be kept"
);
let index_content = read_to_string(temp_path.join("index.md")).unwrap();
assert_eq!(
index_content,
indoc! {"
# Index
## Architecture
Architecture content.
"}
);
}
#[test]
fn test_inline_as_quote() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
(
"quote",
indoc! {"
Quote paragraph 1
Quote paragraph 2
"},
),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "quote", "--as-quote"]);
assert!(output.status.success());
let index_content = read_to_string(temp_path.join("index.md")).unwrap();
assert_eq!(
index_content,
indoc! {"
# Index
> Quote paragraph 1
>
> Quote paragraph 2
"}
);
}
#[test]
fn test_inline_cleans_other_references() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
(
"other",
indoc! {"
# Other
[Also refs target](target)
"},
),
("target", "# Target\n\nContent"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "target"]);
assert!(output.status.success());
let other_content = read_to_string(temp_path.join("other.md")).unwrap();
assert_eq!(other_content, "# Other\n");
}
#[test]
fn test_inline_ambiguous_reference_fails() {
let temp_dir = setup_workspace_with_docs(vec
[Notes B](notes-b)
"},
),
("notes-a", "# Notes A"),
("notes-b", "# Notes B"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "notes"]);
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_eq!(
stderr,
indoc! {"
Error: Multiple references match 'notes':
1: [Notes A](notes-a)
2: [Notes B](notes-b)
Use --block <n> to select a specific reference.
"}
);
}
#[test]
fn test_inline_nonexistent_key() {
let temp_dir = setup_workspace_with_docs(vec![("a", "# Doc A")]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["nonexistent", "--block", "1"]);
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_eq!(stderr, "Error: Document 'nonexistent' not found\n");
}
#[test]
fn test_inline_reference_not_found() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
("target", "# Target"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "nonexistent"]);
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_eq!(stderr, "Error: No reference matches 'nonexistent'\n");
}
#[test]
fn test_inline_block_out_of_range() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
("target", "# Target"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--block", "10"]);
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert_eq!(stderr, "Error: Block number 10 out of range (1-1)\n");
}
#[test]
fn test_inline_dry_run() {
let temp_dir = setup_workspace_with_docs(vec
"},
),
("target", "# Target\n\nContent"),
]);
let temp_path = temp_dir.path();
let original_content = read_to_string(temp_path.join("index.md")).unwrap();
let output = run_inline_command(temp_path, &["index", "--reference", "target", "--dry-run"]);
assert!(output.status.success());
let after_content = read_to_string(temp_path.join("index.md")).unwrap();
assert_eq!(
original_content, after_content,
"File should not be modified"
);
assert!(
temp_path.join("target.md").exists(),
"Target should still exist"
);
}
#[test]
fn test_inline_keys_output() {
let temp_dir = setup_workspace_with_docs(vec"),
("target", "# Target"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(
temp_path,
&["index", "--reference", "target", "--keys", "--dry-run"],
);
let stderr = String::from_utf8(output.stderr.clone()).unwrap();
assert!(output.status.success(), "Command failed: {}", stderr);
let stdout = String::from_utf8(output.stdout).unwrap();
assert_eq!(stdout, "index\ntarget\n");
}
#[test]
fn test_inline_quiet_mode() {
let temp_dir = setup_workspace_with_docs(vec"),
("target", "# Target"),
]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--reference", "target", "--quiet"]);
let stderr = String::from_utf8(output.stderr.clone()).unwrap();
assert!(output.status.success(), "Command failed: {}", stderr);
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(
stdout.trim().is_empty(),
"Quiet mode should suppress output"
);
}
#[test]
fn test_inline_no_references() {
let temp_dir = setup_workspace_with_docs(vec![(
"index",
indoc! {"
# Index
Just regular content, no references.
"},
)]);
let temp_path = temp_dir.path();
let output = run_inline_command(temp_path, &["index", "--list"]);
assert!(output.status.success());
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(
stdout.trim().is_empty(),
"Should have no references to list"
);
}
fn setup_workspace_with_docs(docs: Vec<(&str, &str)>) -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
for (key, content) in docs {
write(temp_path.join(format!("{}.md", key)), content).expect("Should write file");
}
temp_dir
}
fn setup_iwe_config(temp_path: &std::path::Path) {
create_dir_all(temp_path.join(".iwe")).expect("Failed to create .iwe directory");
let config = Configuration {
library: LibraryOptions {
path: "".to_string(),
..Default::default()
},
markdown: MarkdownOptions {
refs_extension: "".to_string(),
..Default::default()
},
..Default::default()
};
let config_content = toml::to_string(&config).expect("Failed to serialize config");
write(temp_path.join(".iwe").join("config.toml"), config_content).expect("Should write config");
}
fn run_inline_command(work_dir: &std::path::Path, args: &[&str]) -> std::process::Output {
let mut command = Command::new(crate::common::get_iwe_binary_path());
command.arg("inline").current_dir(work_dir);
for arg in args {
command.arg(arg);
}
command.output().expect("Failed to execute iwe inline")
}