@@ -2187,3 +2187,154 @@ pub async fn validate_hook_command(command: String) -> Result<serde_json::Value,
21872187 Err ( e) => Err ( format ! ( "Failed to validate command: {}" , e) ) ,
21882188 }
21892189}
2190+
2191+ #[ cfg( test) ]
2192+ mod tests {
2193+ use super :: * ;
2194+ use std:: fs;
2195+ use tempfile:: TempDir ;
2196+
2197+ /// Helper to create a JSONL line with cwd
2198+ fn create_jsonl_line ( cwd : Option < & str > ) -> String {
2199+ let cwd_value = match cwd {
2200+ Some ( path) => format ! ( "\" {}\" " , path) ,
2201+ None => "null" . to_string ( ) ,
2202+ } ;
2203+ format ! ( r#"{{"type":"system","cwd":{}}}"# , cwd_value)
2204+ }
2205+
2206+ #[ test]
2207+ fn test_get_project_path_from_sessions_first_line_valid ( ) {
2208+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2209+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2210+
2211+ // Create a session file with valid cwd on the first line
2212+ let content = create_jsonl_line ( Some ( "/Users/test/project" ) ) ;
2213+ fs:: write ( & session_file, content) . unwrap ( ) ;
2214+
2215+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2216+ assert ! ( result. is_ok( ) ) ;
2217+ assert_eq ! ( result. unwrap( ) , "/Users/test/project" ) ;
2218+ }
2219+
2220+ #[ test]
2221+ fn test_get_project_path_from_sessions_null_then_valid ( ) {
2222+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2223+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2224+
2225+ // Create a session file with null cwd on first line, valid on second
2226+ // This is the bug scenario we're fixing
2227+ let content = format ! (
2228+ "{}\n {}\n {}" ,
2229+ create_jsonl_line( None ) ,
2230+ create_jsonl_line( Some ( "/Users/test/data-discovery" ) ) ,
2231+ create_jsonl_line( Some ( "/Users/test/data-discovery" ) )
2232+ ) ;
2233+ fs:: write ( & session_file, content) . unwrap ( ) ;
2234+
2235+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2236+ assert ! ( result. is_ok( ) ) ;
2237+ assert_eq ! ( result. unwrap( ) , "/Users/test/data-discovery" ) ;
2238+ }
2239+
2240+ #[ test]
2241+ fn test_get_project_path_from_sessions_no_valid_cwd ( ) {
2242+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2243+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2244+
2245+ // Create a session file with only null/missing cwd entries
2246+ let content = format ! (
2247+ "{}\n {}\n {}" ,
2248+ create_jsonl_line( None ) ,
2249+ create_jsonl_line( None ) ,
2250+ r#"{"type":"message","role":"user"}"#
2251+ ) ;
2252+ fs:: write ( & session_file, content) . unwrap ( ) ;
2253+
2254+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2255+ assert ! ( result. is_err( ) ) ;
2256+ assert ! ( result. unwrap_err( ) . contains( "Could not determine project path" ) ) ;
2257+ }
2258+
2259+ #[ test]
2260+ fn test_get_project_path_from_sessions_hyphenated_path ( ) {
2261+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2262+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2263+
2264+ // Test specifically with a path containing hyphens (the original bug)
2265+ let content = format ! (
2266+ "{}\n {}" ,
2267+ create_jsonl_line( None ) ,
2268+ create_jsonl_line( Some ( "/Users/shah/projects/flipside/data-discovery" ) )
2269+ ) ;
2270+ fs:: write ( & session_file, content) . unwrap ( ) ;
2271+
2272+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2273+ assert ! ( result. is_ok( ) ) ;
2274+ // Verify hyphens are preserved (not replaced with slashes)
2275+ assert_eq ! (
2276+ result. unwrap( ) ,
2277+ "/Users/shah/projects/flipside/data-discovery"
2278+ ) ;
2279+ }
2280+
2281+ #[ test]
2282+ fn test_get_project_path_from_sessions_no_jsonl_files ( ) {
2283+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2284+
2285+ // Empty directory with no JSONL files
2286+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2287+ assert ! ( result. is_err( ) ) ;
2288+ }
2289+
2290+ #[ test]
2291+ fn test_get_project_path_from_sessions_multiple_files ( ) {
2292+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2293+
2294+ // Create first session file with no valid cwd
2295+ let session_file1 = temp_dir. path ( ) . join ( "session1.jsonl" ) ;
2296+ fs:: write ( & session_file1, create_jsonl_line ( None ) ) . unwrap ( ) ;
2297+
2298+ // Create second session file with valid cwd
2299+ let session_file2 = temp_dir. path ( ) . join ( "session2.jsonl" ) ;
2300+ fs:: write ( & session_file2, create_jsonl_line ( Some ( "/Users/test/project2" ) ) ) . unwrap ( ) ;
2301+
2302+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2303+ assert ! ( result. is_ok( ) ) ;
2304+ // Should find the valid cwd from one of the files
2305+ assert_eq ! ( result. unwrap( ) , "/Users/test/project2" ) ;
2306+ }
2307+
2308+ #[ test]
2309+ fn test_get_project_path_from_sessions_checks_up_to_10_lines ( ) {
2310+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2311+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2312+
2313+ // Create a file with 9 null cwds and then a valid one on line 10
2314+ let mut lines = vec ! [ create_jsonl_line( None ) ; 9 ] ;
2315+ lines. push ( create_jsonl_line ( Some ( "/Users/test/found-on-line-10" ) ) ) ;
2316+ let content = lines. join ( "\n " ) ;
2317+ fs:: write ( & session_file, content) . unwrap ( ) ;
2318+
2319+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2320+ assert ! ( result. is_ok( ) ) ;
2321+ assert_eq ! ( result. unwrap( ) , "/Users/test/found-on-line-10" ) ;
2322+ }
2323+
2324+ #[ test]
2325+ fn test_get_project_path_from_sessions_stops_after_10_lines ( ) {
2326+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
2327+ let session_file = temp_dir. path ( ) . join ( "test-session.jsonl" ) ;
2328+
2329+ // Create a file with 10 null cwds and a valid one on line 11
2330+ // Should NOT find the valid cwd since we only check first 10 lines
2331+ let mut lines = vec ! [ create_jsonl_line( None ) ; 10 ] ;
2332+ lines. push ( create_jsonl_line ( Some ( "/Users/test/on-line-11" ) ) ) ;
2333+ let content = lines. join ( "\n " ) ;
2334+ fs:: write ( & session_file, content) . unwrap ( ) ;
2335+
2336+ let result = get_project_path_from_sessions ( & temp_dir. path ( ) . to_path_buf ( ) ) ;
2337+ // Should fail since valid cwd is beyond the 10-line limit
2338+ assert ! ( result. is_err( ) ) ;
2339+ }
2340+ }
0 commit comments