mod common;
#[ test ]
fn test_list_verbosity_negative()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "verbosity::-1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 verbosity::-1. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "verbosity" ) ||
combined.to_lowercase().contains( "invalid" ),
"Error should mention verbosity or invalid. Got: {combined}"
);
}
#[ test ]
fn test_list_verbosity_out_of_range()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "verbosity::6" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 verbosity::6. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "verbosity" ) ||
combined.to_lowercase().contains( "invalid" ),
"Error should mention verbosity or invalid. Got: {combined}"
);
}
#[ test ]
fn test_list_verbosity_zero()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-proj-v0", "sess-v0-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::0" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list verbosity::0 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_verbosity_mid_range()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-proj-v3", "sess-v3-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::3" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list verbosity::3 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_verbosity_max()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-proj-v5", "sess-v5-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::5" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list verbosity::5 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_agent_invalid()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "agent::2" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 Boolean agent::2. Got: {combined}"
);
}
#[ test ]
fn test_list_agent_zero()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "agent::0" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list agent::0 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_agent_one()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-proj-ag", "sess-ag-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "agent::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list agent::1 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_session_filter()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-proj-sf", "sess-sf-abc", 2 );
let output = common::clg_cmd()
.args( [ ".list", "session::abc" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list session::abc should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_session_filter_empty()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "session::" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 empty session filter. Got: {combined}"
);
assert!(
combined.contains( "session" ),
"Error should mention session parameter. Got: {combined}"
);
}
#[ test ]
fn test_list_sessions_invalid()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::2" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 Boolean show_sessions::2. Got: {combined}"
);
}
#[ test ]
fn test_list_type_uuid_with_sessions()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-pair-uuid", "sess-uuid-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "type::uuid", "show_sessions::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list type::uuid show_sessions::1 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_type_path_with_verbosity()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-pair-path", "sess-path-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "type::path", "verbosity::2" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list type::path verbosity::2 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_sessions_with_invalid_verbosity()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::0", "verbosity::-1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 verbosity::-1 even alongside valid show_sessions::0. Got: {combined}"
);
}
#[ test ]
fn test_list_no_params()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-base-proj", "sess-base-001", 2 );
let output = common::clg_cmd()
.args( [ ".list" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list with no params should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_sessions_zero()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-s0-proj", "sess-s0-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::0" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list show_sessions::0 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_sessions_one()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-s1-proj", "sess-s1-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list show_sessions::1 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_min_entries_zero()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-me-proj", "sess-me-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "min_entries::0" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list min_entries::0 should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_path_filter()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "path::/tmp" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list path::/tmp should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_type_all()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-tall-proj", "sess-tall-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "type::all" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list type::all should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_type_invalid()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
let output = common::clg_cmd()
.args( [ ".list", "type::notvalid" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
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 type. Got: {combined}"
);
assert!(
combined.to_lowercase().contains( "type" ) ||
combined.to_lowercase().contains( "invalid" ),
"Error should mention type or invalid. Got: {combined}"
);
}
#[ test ]
fn test_list_verbosity_default_explicit()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "list-vdef-proj", "sess-vdef-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stderr = String::from_utf8_lossy( &output.stderr );
assert!(
output.status.success(),
".list verbosity::1 (default) should succeed. stderr: {stderr}"
);
}
#[ test ]
fn test_list_singular_noun_one_project()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "only-proj", "sess-sing-001", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stdout = String::from_utf8_lossy( &output.stdout );
assert!(
output.status.success(),
".list with 1 project should succeed; stderr: {}",
String::from_utf8_lossy( &output.stderr )
);
assert!(
stdout.contains( "Found 1 project:" ),
"with 1 project, header must use singular 'project'; got:\n{stdout}"
);
assert!(
!stdout.contains( "Found 1 projects:" ),
"with 1 project, header must NOT use plural 'projects'; got:\n{stdout}"
);
}
#[ test ]
fn test_list_plural_noun_multiple_projects()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "proj-a", "sess-plur-a", 2 );
common::write_test_session( storage.path(), "proj-b", "sess-plur-b", 2 );
let output = common::clg_cmd()
.args( [ ".list", "verbosity::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stdout = String::from_utf8_lossy( &output.stdout );
assert!(
output.status.success(),
".list with 2 projects should succeed; stderr: {}",
String::from_utf8_lossy( &output.stderr )
);
assert!(
stdout.contains( "Found 2 projects:" ),
"with 2 projects, header must use plural 'projects'; got:\n{stdout}"
);
}
#[ test ]
fn test_list_session_count_singular_when_one_session()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "sing-proj", "sess-sing-only", 2 );
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stdout = String::from_utf8_lossy( &output.stdout );
assert!(
output.status.success(),
".list show_sessions::1 should succeed; stderr: {}",
String::from_utf8_lossy( &output.stderr )
);
assert!(
stdout.contains( "(1 conversation)" ),
"with 1 conversation, project label must use singular '(1 conversation)'; got:\n{stdout}"
);
assert!(
!stdout.contains( "(1 conversations)" ),
"with 1 conversation, project label must NOT use plural '(1 conversations)'; got:\n{stdout}"
);
}
#[ test ]
fn test_list_session_count_plural_when_multiple_sessions()
{
use tempfile::TempDir;
let storage = TempDir::new().unwrap();
common::write_test_session( storage.path(), "plur-proj", "sess-plur-x", 2 );
common::write_test_session( storage.path(), "plur-proj", "sess-plur-y", 2 );
let output = common::clg_cmd()
.args( [ ".list", "show_sessions::1" ] )
.env( "CLAUDE_STORAGE_ROOT", storage.path() )
.output()
.expect( "Failed to execute .list" );
let stdout = String::from_utf8_lossy( &output.stdout );
assert!(
output.status.success(),
".list show_sessions::1 should succeed; stderr: {}",
String::from_utf8_lossy( &output.stderr )
);
assert!(
stdout.contains( "(2 conversations)" ),
"with 2 conversations, project label must use plural '(2 conversations)'; got:\n{stdout}"
);
}
#[ test ]
fn it_list_type_conversation_outputs_ids()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-conv" );
let encoded = common::write_path_project_session( &storage_root, &project, "sess-conv-001", 2 );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout );
assert!( !s.is_empty(), "output must be non-empty when project has sessions; got:\n{s}" );
}
#[ test ]
fn it_list_type_conversation_requires_project()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.output()
.unwrap();
assert!(
!out.status.success(),
".list type::conversation without project:: must exit non-0; got: {:?}",
out.status.code(),
);
}
#[ test ]
fn it_list_count_mode_outputs_integer()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-count" );
let encoded = common::write_path_project_session( &storage_root, &project, "sess-count-001", 2 );
common::write_path_project_session( &storage_root, &project, "sess-count-002", 2 );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( "count::1" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list count::1 must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout ).trim().to_string();
assert!(
s.parse::< usize >().is_ok(),
"count mode must output a bare integer; got: '{s}'",
);
assert_eq!( s, "2", "expected 2 conversations for 2 sessions; got: '{s}'" );
}
#[ test ]
fn it_list_type_conversation_exact_line_count()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-cc-l01" );
let encoded = common::write_path_project_session( &storage_root, &project, "sess-l01-a", 2 );
common::write_path_project_session( &storage_root, &project, "sess-l01-b", 2 );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout );
let lines : Vec< &str > = s.lines().filter( | l | !l.is_empty() ).collect();
assert_eq!(
lines.len(),
2,
"2 sessions → 2 conversation ID lines; got {} line(s):\n{s}",
lines.len(),
);
}
#[ test ]
fn it_list_type_conversation_empty_project()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-cc-l02-empty" );
let encoded = claude_storage_core::encode_path( &project )
.expect( "encode project path" );
let dir = storage_root.join( "projects" ).join( &encoded );
std::fs::create_dir_all( &dir ).unwrap();
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation on empty project must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout ).trim().to_string();
assert!(
s.is_empty(),
"empty project must produce empty output; got: '{s}'"
);
}
#[ test ]
fn it_list_count_zero_means_full_list()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-cc-l03" );
let encoded = common::write_path_project_session( &storage_root, &project, "sess-l03-a", 2 );
common::write_path_project_session( &storage_root, &project, "sess-l03-b", 2 );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( "count::0" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation count::0 must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout ).trim().to_string();
assert!(
s.parse::< usize >().is_err(),
"count::0 must produce list output (not bare integer); got: '{s}'"
);
let lines : Vec< &str > = s.lines().filter( | l | !l.is_empty() ).collect();
assert_eq!(
lines.len(),
2,
"count::0 full list must have 2 lines for 2 sessions; got {} line(s):\n{s}",
lines.len(),
);
}
#[ test ]
fn it_list_count_mode_zero_sessions()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-cc-l04-empty" );
let encoded = claude_storage_core::encode_path( &project )
.expect( "encode project path" );
let dir = storage_root.join( "projects" ).join( &encoded );
std::fs::create_dir_all( &dir ).unwrap();
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( "count::1" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation count::1 on empty project must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout ).trim().to_string();
assert_eq!( s, "0", "count::1 on empty project must output '0'; got: '{s}'" );
}
#[ test ]
fn it_list_count_mode_one_session()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let project = root.path().join( "proj-cc-l05" );
let encoded = common::write_path_project_session( &storage_root, &project, "sess-l05-only", 2 );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( "count::1" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
out.status.success(),
".list type::conversation count::1 must exit 0; stderr: {}",
String::from_utf8_lossy( &out.stderr ),
);
let s = String::from_utf8_lossy( &out.stdout ).trim().to_string();
assert_eq!( s, "1", "1 session → 1 conversation in count mode; got: '{s}'" );
}
#[ test ]
fn it_list_type_conversation_nonexistent_project_fails()
{
use tempfile::TempDir;
let root = TempDir::new().unwrap();
let storage_root = root.path().join( ".claude" );
let fake_project = root.path().join( "nonexistent-proj-l06" );
let encoded = claude_storage_core::encode_path( &fake_project )
.expect( "encode project path" );
let out = common::clg_cmd()
.env( "HOME", root.path().to_str().unwrap() )
.env( "CLAUDE_STORAGE_ROOT", storage_root.to_str().unwrap() )
.arg( ".list" )
.arg( "type::conversation" )
.arg( format!( "project::{encoded}" ) )
.output()
.unwrap();
assert!(
!out.status.success(),
".list type::conversation with nonexistent project must exit non-0; stdout: {}; stderr: {}",
String::from_utf8_lossy( &out.stdout ),
String::from_utf8_lossy( &out.stderr ),
);
}