mod common;
use tempfile::TempDir;
#[test]
fn test_export_session_id_required()
{
let output = common::clg_cmd()
.args( [ ".export", "output::/tmp/test.md" ] )
.current_dir( env!( "CARGO_MANIFEST_DIR" ) )
.output()
.expect( "Failed to execute command" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail when session_id missing. Got: {combined}"
);
assert!(
( combined.to_lowercase().contains( "session" ) ||
combined.to_lowercase().contains( "session_id" ) ) &&
combined.to_lowercase().contains( "required" ),
"Error should mention session_id is required. Got: {combined}"
);
}
#[test]
fn test_export_output_required()
{
let output = common::clg_cmd()
.args( [ ".export", "session_id::test" ] )
.current_dir( env!( "CARGO_MANIFEST_DIR" ) )
.output()
.expect( "Failed to execute command" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail when output missing. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "output" ) &&
combined.to_lowercase().contains( "required" ),
"Error should mention output is required. Got: {combined}"
);
}
#[test]
fn test_export_format_invalid()
{
let output = common::clg_cmd()
.args( [ ".export", "session_id::test", "output::/tmp/test.csv", "format::csv" ] )
.current_dir( env!( "CARGO_MANIFEST_DIR" ) )
.output()
.expect( "Failed to execute command" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail with invalid format. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "format" ) ||
combined.to_lowercase().contains( "invalid" ),
"Error should mention format validation. Got: {combined}"
);
}
#[test]
fn test_export_format_valid()
{
let storage = TempDir::new().unwrap();
let out_dir = TempDir::new().unwrap();
let session_id = "aabbcc11-1111-2222-3333-444444444444";
common::write_test_session( storage.path(), "export-proj", session_id, 4 );
for ( format, ext ) in [ ( "markdown", "md" ), ( "json", "json" ), ( "text", "txt" ) ]
{
let out_file = out_dir.path().join( format!( "export.{ext}" ) );
let output = common::clg_cmd()
.args( [
".export",
&format!( "session_id::{session_id}" ),
&format!( "output::{}", out_file.display() ),
&format!( "format::{format}" ),
"project::export-proj",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
output.status.success(),
".export format::{format} should succeed. Got: {combined}"
);
assert!(
out_file.exists(),
".export format::{format} should create output file"
);
}
}
#[test]
fn test_export_session_nonexistent()
{
let storage = TempDir::new().unwrap();
let out_dir = TempDir::new().unwrap();
common::write_test_session( storage.path(), "export-proj-ne", "real-session-001", 2 );
let out_file = out_dir.path().join( "out.md" );
let output = common::clg_cmd()
.args( [
".export",
"session_id::nonexistent-session-99999",
&format!( "output::{}", out_file.display() ),
"project::export-proj-ne",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail with nonexistent session. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "session" ) &&
( combined.to_lowercase().contains( "not found" ) ||
combined.to_lowercase().contains( "does not exist" ) ||
combined.to_lowercase().contains( "no session" ) ),
"Error should mention session not found. Got: {combined}"
);
}
#[test]
fn test_export_output_directory_nonexistent()
{
let storage = TempDir::new().unwrap();
let session_id = "aabbcc22-1111-2222-3333-000000000000";
common::write_test_session( storage.path(), "export-proj-dir", session_id, 2 );
let output = common::clg_cmd()
.args( [
".export",
&format!( "session_id::{session_id}" ),
"output::/nonexistent/directory/path/out.md",
"project::export-proj-dir",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail with nonexistent output directory. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "directory" ) ||
combined.to_lowercase().contains( "path" ) ||
combined.to_lowercase().contains( "not found" ) ||
combined.to_lowercase().contains( "does not exist" ) ||
combined.to_lowercase().contains( "no such" ),
"Error should mention directory/path issue. Got: {combined}"
);
}
#[test]
fn test_export_with_required_parameters()
{
let storage = TempDir::new().unwrap();
let out_dir = TempDir::new().unwrap();
let session_id = "aabbcc33-1111-2222-3333-555555555555";
common::write_test_session( storage.path(), "export-proj-req", session_id, 3 );
let out_file = out_dir.path().join( "required_params.md" );
let output = common::clg_cmd()
.args( [
".export",
&format!( "session_id::{session_id}" ),
&format!( "output::{}", out_file.display() ),
"project::export-proj-req",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
assert!(
output.status.success(),
"Should succeed with both required params. stderr: {stderr}, stdout: {stdout}"
);
}
#[test]
fn test_export_output_path_in_error_message()
{
let storage = TempDir::new().unwrap();
let session_id = "aabbcc55-1111-2222-3333-777777777777";
common::write_test_session( storage.path(), "export-proj-err", session_id, 2 );
let output = common::clg_cmd()
.args( [
".export",
&format!( "session_id::{session_id}" ),
"output::/nonexistent/dir/export.md",
"project::export-proj-err",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
!output.status.success(),
"Should fail with nonexistent output directory. Got: {combined}"
);
assert!(
combined.contains( "/nonexistent/dir/export.md" ),
"Error must include the output path for diagnostics; got: {combined}"
);
assert!(
!combined.contains( "unknown operation" ),
"Error must not say 'unknown operation' — use specific file context; got: {combined}"
);
}
#[test]
fn test_export_default_format_markdown()
{
let storage = TempDir::new().unwrap();
let out_dir = TempDir::new().unwrap();
let session_id = "aabbcc44-1111-2222-3333-666666666666";
common::write_test_session( storage.path(), "export-proj-def", session_id, 2 );
let out_file = out_dir.path().join( "default_format.md" );
let output = common::clg_cmd()
.args( [
".export",
&format!( "session_id::{session_id}" ),
&format!( "output::{}", out_file.display() ),
"project::export-proj-def",
] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .export" );
let stderr = String::from_utf8_lossy( &output.stderr );
let stdout = String::from_utf8_lossy( &output.stdout );
let combined = format!( "{stderr}{stdout}" );
assert!(
output.status.success(),
"Default format (markdown) should succeed. Got: {combined}"
);
assert!(
out_file.exists(),
"Output file should be created with default format"
);
let content = std::fs::read_to_string( &out_file ).unwrap();
assert!(
content.contains( '#' ),
"Markdown output should contain headers. Got:\n{content}"
);
}