@@ -82,6 +82,34 @@ fn write_xcstrings_multilang_fixture(path: &std::path::Path) {
8282 fs:: write ( path, xcstrings) . unwrap ( ) ;
8383}
8484
85+ fn write_xcstrings_partial_match_fixture ( path : & std:: path:: Path ) {
86+ let xcstrings = r#"{
87+ "sourceLanguage": "en",
88+ "version": "1.0",
89+ "strings": {
90+ "needs_review_key": {
91+ "localizations": {
92+ "en": {
93+ "stringUnit": {
94+ "state": "needs_review",
95+ "value": "Needs review EN"
96+ }
97+ },
98+ "fr": {
99+ "stringUnit": {
100+ "state": "translated",
101+ "value": "Besoin de revision FR"
102+ }
103+ }
104+ }
105+ }
106+ }
107+ }
108+ "# ;
109+
110+ fs:: write ( path, xcstrings) . unwrap ( ) ;
111+ }
112+
85113#[ test]
86114fn test_view_status_filters_single_status_for_lang ( ) {
87115 let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
@@ -431,11 +459,84 @@ fn test_view_status_json_keys_only_outputs_keys_payload() {
431459 assert_eq ! ( payload[ "summary" ] [ "statuses" ] [ "needs_review" ] , 2 ) ;
432460 assert ! ( payload. get( "entries" ) . is_none( ) , "Expected keys-only payload" ) ;
433461
434- let keys = payload[ "keys" ] . as_object ( ) . unwrap ( ) ;
435- let en_keys = keys[ "en" ] . as_array ( ) . unwrap ( ) ;
436- let fr_keys = keys[ "fr" ] . as_array ( ) . unwrap ( ) ;
437- assert_eq ! ( en_keys. len( ) , 1 ) ;
438- assert_eq ! ( fr_keys. len( ) , 1 ) ;
439- assert_eq ! ( en_keys[ 0 ] , "needs_review_key" ) ;
440- assert_eq ! ( fr_keys[ 0 ] , "needs_review_key" ) ;
462+ let keys = payload[ "keys" ] . as_array ( ) . unwrap ( ) ;
463+ assert_eq ! ( keys. len( ) , 2 ) ;
464+ assert ! (
465+ keys. iter( )
466+ . any( |item| item[ "lang" ] == "en" && item[ "key" ] == "needs_review_key" )
467+ ) ;
468+ assert ! (
469+ keys. iter( )
470+ . any( |item| item[ "lang" ] == "fr" && item[ "key" ] == "needs_review_key" )
471+ ) ;
472+ }
473+
474+ #[ test]
475+ fn test_view_status_json_excludes_zero_match_languages_in_summary ( ) {
476+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
477+ let input_file = temp_dir. path ( ) . join ( "Localizable.xcstrings" ) ;
478+ write_xcstrings_partial_match_fixture ( & input_file) ;
479+
480+ let output = langcodec_cmd ( )
481+ . args ( [
482+ "view" ,
483+ "-i" ,
484+ input_file. to_str ( ) . unwrap ( ) ,
485+ "--status" ,
486+ "needs_review" ,
487+ "--json" ,
488+ ] )
489+ . output ( )
490+ . unwrap ( ) ;
491+
492+ assert ! (
493+ output. status. success( ) ,
494+ "CLI failed: {}" ,
495+ String :: from_utf8_lossy( & output. stderr)
496+ ) ;
497+
498+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
499+ let payload: serde_json:: Value = serde_json:: from_str ( & stdout)
500+ . unwrap_or_else ( |e| panic ! ( "Expected JSON output. parse error: {e}. stdout: {stdout}" ) ) ;
501+
502+ let languages = payload[ "summary" ] [ "languages" ] . as_array ( ) . unwrap ( ) ;
503+ assert_eq ! ( languages. len( ) , 1 ) ;
504+ assert_eq ! ( languages[ 0 ] , "en" ) ;
505+ }
506+
507+ #[ test]
508+ fn test_view_status_json_keys_only_lang_uses_consistent_object_schema ( ) {
509+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
510+ let input_file = temp_dir. path ( ) . join ( "Localizable.xcstrings" ) ;
511+ write_xcstrings_multilang_fixture ( & input_file) ;
512+
513+ let output = langcodec_cmd ( )
514+ . args ( [
515+ "view" ,
516+ "-i" ,
517+ input_file. to_str ( ) . unwrap ( ) ,
518+ "--lang" ,
519+ "en" ,
520+ "--status" ,
521+ "needs_review" ,
522+ "--keys-only" ,
523+ "--json" ,
524+ ] )
525+ . output ( )
526+ . unwrap ( ) ;
527+
528+ assert ! (
529+ output. status. success( ) ,
530+ "CLI failed: {}" ,
531+ String :: from_utf8_lossy( & output. stderr)
532+ ) ;
533+
534+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
535+ let payload: serde_json:: Value = serde_json:: from_str ( & stdout)
536+ . unwrap_or_else ( |e| panic ! ( "Expected JSON output. parse error: {e}. stdout: {stdout}" ) ) ;
537+
538+ let keys = payload[ "keys" ] . as_array ( ) . unwrap ( ) ;
539+ assert ! ( !keys. is_empty( ) , "Expected at least one key object" ) ;
540+ assert ! ( keys. iter( ) . all( |item| item[ "lang" ] == "en" ) ) ;
541+ assert ! ( keys. iter( ) . all( |item| item[ "key" ] == "needs_review_key" ) ) ;
441542}
0 commit comments