@@ -798,3 +798,105 @@ def test_run_hook_basic(server: Server) -> None:
798798
799799 # Cleanup
800800 session .unset_hook ("session-renamed" )
801+
802+
803+ # =============================================================================
804+ # set_hook Flag Combination Tests
805+ # =============================================================================
806+
807+
808+ class SetHookFlagTestCase (t .NamedTuple ):
809+ """Test case for set_hook flag combinations."""
810+
811+ test_id : str
812+ flag_kwargs : dict [str , t .Any ]
813+ expected_behavior : str # "sets_hook", "runs_immediately", "appends", "global"
814+ min_version : str = "3.2"
815+
816+
817+ SET_HOOK_FLAG_TEST_CASES : list [SetHookFlagTestCase ] = [
818+ SetHookFlagTestCase (
819+ "append_to_existing" ,
820+ {"append" : True },
821+ "appends" ,
822+ ),
823+ SetHookFlagTestCase (
824+ "global_hook" ,
825+ {"global_" : True },
826+ "global" ,
827+ ),
828+ SetHookFlagTestCase (
829+ "run_immediately" ,
830+ {"run" : True },
831+ "runs_immediately" ,
832+ ),
833+ SetHookFlagTestCase (
834+ "append_and_global" ,
835+ {"append" : True , "global_" : True },
836+ "appends" ,
837+ ),
838+ ]
839+
840+
841+ @pytest .mark .parametrize (
842+ "test_case" ,
843+ [pytest .param (tc , id = tc .test_id ) for tc in SET_HOOK_FLAG_TEST_CASES ],
844+ )
845+ def test_set_hook_flag_combinations (
846+ server : Server ,
847+ test_case : SetHookFlagTestCase ,
848+ ) -> None :
849+ """Test set_hook with various flag combinations."""
850+ if not has_gte_version (test_case .min_version ):
851+ pytest .skip (f"Requires tmux { test_case .min_version } +" )
852+
853+ session = server .new_session (session_name = "test_flags" )
854+
855+ hook_name = "session-renamed"
856+ hook_cmd = "display-message 'flag test'"
857+
858+ if test_case .expected_behavior == "appends" :
859+ # Set initial hook first
860+ session .set_hook (f"{ hook_name } [0]" , "display-message 'initial'" )
861+ session .set_hook (hook_name , hook_cmd , ** test_case .flag_kwargs )
862+
863+ # Verify append added another entry
864+ if test_case .flag_kwargs .get ("global_" ):
865+ # Use raw command for global hooks
866+ result = server .cmd ("show-hooks" , "-g" , hook_name )
867+ assert result .stdout is not None
868+ parsed = Hooks .from_stdout (result .stdout )
869+ else :
870+ hooks = session ._show_hook (hook_name )
871+ assert hooks is not None
872+ parsed = Hooks .from_stdout (hooks )
873+
874+ hook_values = parsed .session_renamed .as_list ()
875+ assert len (hook_values ) >= 1
876+
877+ elif test_case .expected_behavior == "global" :
878+ session .set_hook (f"{ hook_name } [0]" , hook_cmd , ** test_case .flag_kwargs )
879+
880+ # Global hook should be visible from server with -g flag
881+ result = server .cmd ("show-hooks" , "-g" , f"{ hook_name } [0]" )
882+ assert result .stdout is not None
883+ assert len (result .stdout ) > 0
884+ assert "display-message" in result .stdout [0 ]
885+
886+ elif test_case .expected_behavior == "runs_immediately" :
887+ # The -R flag runs hook immediately WITHOUT storing
888+ # So after set_hook with run=True, hook should NOT be stored
889+ session .set_hook (hook_name , hook_cmd , ** test_case .flag_kwargs )
890+
891+ # Hook should NOT be stored (run immediately and discarded)
892+ hooks = session ._show_hook (hook_name )
893+ # Either None or empty
894+ if hooks :
895+ parsed = Hooks .from_stdout (hooks )
896+ # May be empty or have default empty entry
897+ assert parsed .session_renamed is None or len (parsed .session_renamed ) == 0
898+
899+ # Cleanup
900+ session .unset_hook (hook_name )
901+ if test_case .flag_kwargs .get ("global_" ):
902+ server .cmd ("set-hook" , "-gu" , hook_name )
0 commit comments