use diwe::config::{Configuration, LibraryOptions, MarkdownOptions};
use indoc::indoc;
use std::fs::{create_dir_all, write};
use std::process::Command;
use tempfile::TempDir;
#[test]
fn test_squash_basic_functionality() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(!stdout.trim().is_empty(), "Should produce some output");
assert!(
stdout.contains("#") || stdout.contains("*") || stdout.contains("-"),
"Should contain markdown formatting"
);
}
#[test]
fn test_squash_with_depth_limit() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test", "--depth", "1"]);
assert!(
output.status.success(),
"Squash command with depth should succeed"
);
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(
!stdout.trim().is_empty(),
"Should produce output with depth limit"
);
}
#[test]
fn test_squash_with_higher_depth() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test", "--depth", "5"]);
assert!(
output.status.success(),
"Squash command with higher depth should succeed"
);
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(
!stdout.trim().is_empty(),
"Should produce output with higher depth"
);
}
#[test]
fn test_squash_default_depth() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(
!stdout.trim().is_empty(),
"Should produce output with default depth"
);
}
#[test]
fn test_squash_nonexistent_key() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["nonexistent"]);
assert!(
!output.status.success(),
"Squash should fail with nonexistent key"
);
let stderr = String::from_utf8(output.stderr).expect("Valid UTF-8 stderr");
assert_eq!(stderr, "Error: Document 'nonexistent' not found\n");
}
#[test]
fn test_squash_complex_workspace() {
let temp_dir = setup_complex_test_workspace();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["document1"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(
!stdout.trim().is_empty(),
"Should produce output from complex workspace"
);
}
#[test]
fn test_squash_with_links() {
let temp_dir = setup_test_workspace_with_links();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["main"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(
!stdout.trim().is_empty(),
"Should produce output for linked documents"
);
}
#[test]
fn test_squash_preserves_markdown_structure() {
let temp_dir = setup_test_workspace_with_structured_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["structured"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
let has_headers = stdout.contains('#');
let has_lists = stdout.contains('-') || stdout.contains('*') || stdout.contains("1.");
assert!(
has_headers || has_lists || !stdout.trim().is_empty(),
"Should preserve some markdown structure or content"
);
}
#[test]
fn test_squash_with_verbose_flag() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = Command::new(crate::common::get_iwe_binary_path())
.arg("squash")
.arg("test")
.arg("--verbose")
.arg("1")
.current_dir(temp_path)
.output()
.expect("Failed to execute iwe squash");
assert!(
output.status.success(),
"Squash with verbose flag should succeed"
);
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
assert!(!stdout.trim().is_empty(), "Should produce output");
}
#[test]
fn test_squash_zero_depth() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test", "--depth", "0"]);
assert!(
output.status.success(),
"Squash command with depth 0 should succeed"
);
let _stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
}
#[test]
fn test_squash_key_with_spaces() {
let temp_dir = setup_test_workspace_with_spaced_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["spaced key"]);
assert!(
output.status.success(),
"Squash should handle keys with spaces"
);
let _stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
}
#[test]
fn test_squash_empty_workspace() {
let temp_dir = setup_empty_workspace();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["anything"]);
assert!(
!output.status.success(),
"Squash should fail with empty workspace and nonexistent key"
);
let stderr = String::from_utf8(output.stderr).expect("Valid UTF-8 stderr");
assert!(
!stderr.is_empty(),
"Should have error output for empty workspace"
);
}
#[test]
fn test_squash_without_config() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
let markdown_content = indoc! {"
# Test Document
This is a test document.
## Section 1
Some content here.
"};
write(temp_path.join("test.md"), markdown_content).expect("Should write test file");
let output = run_squash_command(temp_path, &["test"]);
assert!(
output.status.success(),
"Squash should work without explicit config"
);
}
#[test]
fn test_squash_stderr_empty() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test"]);
assert!(output.status.success(), "Squash command should succeed");
let stderr = String::from_utf8(output.stderr).expect("Valid UTF-8 stderr");
assert!(
stderr.is_empty() || (!stderr.contains("ERROR") && !stderr.contains("error:")),
"Squash stderr should not contain errors: {}",
stderr
);
}
#[test]
fn test_squash_output_is_markdown() {
let temp_dir = setup_test_workspace_with_content();
let temp_path = temp_dir.path();
let output = run_squash_command(temp_path, &["test"]);
assert!(output.status.success(), "Squash command should succeed");
let stdout = String::from_utf8(output.stdout).expect("Valid UTF-8 output");
if !stdout.trim().is_empty() {
let has_markdown_elements = stdout.contains('#')
|| stdout.contains('*')
|| stdout.contains('-')
|| stdout.contains('[')
|| stdout.lines().any(|line| !line.trim().is_empty());
assert!(
has_markdown_elements,
"Output should contain markdown-like elements or be empty"
);
}
}
fn setup_test_workspace_with_content() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
let markdown_content = indoc! {"
# Test Document
This is a test document with some content.
## Section 1
Some content here.
### Subsection
More content.
## Section 2
Additional content.
"};
write(temp_path.join("test.md"), markdown_content).expect("Should write test file");
temp_dir
}
fn setup_complex_test_workspace() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
let file1_content = indoc! {"
# Document 1
Content for document 1.
## Section A
Content A.
### Subsection A1
Nested content.
"};
let file2_content = indoc! {"
# Document 2
Content for document 2.
## Section B
Content B.
## Section C
Content C.
"};
let nested_content = indoc! {"
# Nested Document
Nested content here.
## Nested Section
More nested content.
"};
write(temp_path.join("document1.md"), file1_content).expect("Should write file1");
write(temp_path.join("document2.md"), file2_content).expect("Should write file2");
create_dir_all(temp_path.join("subdirectory")).expect("Should create subdirectory");
write(
temp_path.join("subdirectory").join("document_nested.md"),
nested_content,
)
.expect("Should write nested file");
temp_dir
}
fn setup_test_workspace_with_links() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
let main_content = indoc! {"
# Main Document
This document links to [target](target.md).
## Section
More content with links.
### Subsection
Content with links.
"};
let target_content = indoc! {"
# Target Document
This is the target of the link.
## Target Section
Target content.
"};
write(temp_path.join("main.md"), main_content).expect("Should write main file");
write(temp_path.join("target.md"), target_content).expect("Should write target file");
temp_dir
}
fn setup_test_workspace_with_structured_content() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
let structured_content = indoc! {"
# Structured Document
This document has various markdown elements.
## Lists
Unordered list:
- Item 1
- Item 2
- Nested item
Ordered list:
1. First item
2. Second item
1. Nested ordered item
## Code
```rust
fn hello() {
println!(\"Hello, world!\");
}
```
## Links and References
Link to [external site](https://example.com).
Reference to another document: [Document 1](document1).
## Tables
| Column 1 | Column 2 |
|----------|----------|
| Value 1 | Value 2 |
"};
write(temp_path.join("structured.md"), structured_content)
.expect("Should write structured file");
temp_dir
}
fn setup_test_workspace_with_spaced_content() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
let content = indoc! {"
# Spaced Key Document
This document has a title with spaces.
## Section
Content here.
"};
write(temp_path.join("spaced key.md"), content).expect("Should write spaced file");
temp_dir
}
fn setup_empty_workspace() -> TempDir {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let temp_path = temp_dir.path();
setup_iwe_config(temp_path);
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 to TOML");
write(temp_path.join(".iwe").join("config.toml"), config_content)
.expect("Should write config file");
}
fn run_squash_command(work_dir: &std::path::Path, args: &[&str]) -> std::process::Output {
let mut command = Command::new(crate::common::get_iwe_binary_path());
command.arg("squash").current_dir(work_dir);
for arg in args {
command.arg(arg);
}
command.output().expect("Failed to execute iwe squash")
}