99 "testing"
1010
1111 flashduty "github.com/flashcatcloud/flashduty-sdk"
12+ "github.com/spf13/cobra"
13+ "github.com/spf13/pflag"
1214)
1315
1416// mockClient provides default "not implemented" stubs for all flashdutyClient
@@ -71,38 +73,42 @@ func (m *mockClient) DisableIncidentMerge(context.Context, []string) error {
7173 return fmt .Errorf ("mockClient: DisableIncidentMerge not implemented" )
7274}
7375
74- func (m * mockClient ) CommentIncidents (context.Context , * IncidentCommentInput ) error {
76+ func (m * mockClient ) CommentIncidents (context.Context , * flashduty. IncidentCommentInput ) error {
7577 return fmt .Errorf ("mockClient: CommentIncidents not implemented" )
7678}
7779
78- func (m * mockClient ) AddIncidentResponders (context.Context , * IncidentAddResponderInput ) error {
80+ func (m * mockClient ) AddIncidentResponders (context.Context , * flashduty. IncidentAddResponderInput ) error {
7981 return fmt .Errorf ("mockClient: AddIncidentResponders not implemented" )
8082}
8183
82- func (m * mockClient ) CreateIncidentWarRoom (context.Context , * IncidentWarRoomCreateInput ) (* IncidentWarRoom , error ) {
84+ func (m * mockClient ) CreateIncidentWarRoom (context.Context , * flashduty. IncidentWarRoomCreateInput ) (* flashduty. IncidentWarRoom , error ) {
8385 return nil , fmt .Errorf ("mockClient: CreateIncidentWarRoom not implemented" )
8486}
8587
86- func (m * mockClient ) ListIncidentWarRooms (context.Context , * IncidentWarRoomListInput ) (* IncidentWarRoomListOutput , error ) {
88+ func (m * mockClient ) ListIncidentWarRooms (context.Context , * flashduty. IncidentWarRoomListInput ) (* flashduty. IncidentWarRoomListOutput , error ) {
8789 return nil , fmt .Errorf ("mockClient: ListIncidentWarRooms not implemented" )
8890}
8991
90- func (m * mockClient ) GetIncidentWarRoom (context.Context , * IncidentWarRoomDetailInput ) (* IncidentWarRoom , error ) {
92+ func (m * mockClient ) GetIncidentWarRoom (context.Context , * flashduty. IncidentWarRoomDetailInput ) (* flashduty. IncidentWarRoom , error ) {
9193 return nil , fmt .Errorf ("mockClient: GetIncidentWarRoom not implemented" )
9294}
9395
94- func (m * mockClient ) DeleteIncidentWarRoom (context.Context , * IncidentWarRoomDeleteInput ) error {
96+ func (m * mockClient ) DeleteIncidentWarRoom (context.Context , * flashduty. IncidentWarRoomDeleteInput ) error {
9597 return fmt .Errorf ("mockClient: DeleteIncidentWarRoom not implemented" )
9698}
9799
98- func (m * mockClient ) AddIncidentWarRoomMembers (context.Context , * IncidentWarRoomAddMemberInput ) error {
100+ func (m * mockClient ) AddIncidentWarRoomMembers (context.Context , * flashduty. IncidentWarRoomAddMemberInput ) error {
99101 return fmt .Errorf ("mockClient: AddIncidentWarRoomMembers not implemented" )
100102}
101103
102- func (m * mockClient ) GetIncidentWarRoomDefaultObservers (context.Context , string ) ([]IncidentWarRoomObserver , error ) {
104+ func (m * mockClient ) GetIncidentWarRoomDefaultObservers (context.Context , string ) ([]flashduty. IncidentWarRoomObserver , error ) {
103105 return nil , fmt .Errorf ("mockClient: GetIncidentWarRoomDefaultObservers not implemented" )
104106}
105107
108+ func (m * mockClient ) ListWarRoomEnabledDataSources (context.Context ) (* flashduty.ListWarRoomEnabledDataSourcesOutput , error ) {
109+ return nil , fmt .Errorf ("mockClient: ListWarRoomEnabledDataSources not implemented" )
110+ }
111+
106112func (m * mockClient ) ListChannels (context.Context , * flashduty.ListChannelsInput ) (* flashduty.ListChannelsOutput , error ) {
107113 return nil , fmt .Errorf ("mockClient: ListChannels not implemented" )
108114}
@@ -307,6 +313,8 @@ func saveAndResetGlobals(t *testing.T) {
307313// and returns (stdout string, error). It also resets cobra flag state after
308314// execution.
309315func execCommand (args ... string ) (string , error ) {
316+ resetCommandFlags (rootCmd )
317+
310318 buf := new (bytes.Buffer )
311319 rootCmd .SetOut (buf )
312320 rootCmd .SetErr (buf )
@@ -319,10 +327,35 @@ func execCommand(args ...string) (string, error) {
319327 rootCmd .SetArgs (nil )
320328 rootCmd .SetOut (nil )
321329 rootCmd .SetErr (nil )
330+ resetCommandFlags (rootCmd )
322331
323332 return buf .String (), err
324333}
325334
335+ func resetCommandFlags (cmd * cobra.Command ) {
336+ if cmd == nil {
337+ return
338+ }
339+ resetFlagSet (cmd .Flags ())
340+ resetFlagSet (cmd .PersistentFlags ())
341+ for _ , child := range cmd .Commands () {
342+ resetCommandFlags (child )
343+ }
344+ }
345+
346+ func resetFlagSet (flags * pflag.FlagSet ) {
347+ if flags == nil {
348+ return
349+ }
350+ flags .VisitAll (func (flag * pflag.Flag ) {
351+ switch flag .Value .Type () {
352+ case "bool" , "int" , "int64" , "string" :
353+ _ = flag .Value .Set (flag .DefValue )
354+ flag .Changed = false
355+ }
356+ })
357+ }
358+
326359// ---------------------------------------------------------------------------
327360// Test 191: incident get returns empty results
328361// ---------------------------------------------------------------------------
@@ -665,8 +698,8 @@ type mockIncidentLifecycle struct {
665698 wakeIDs []string
666699 removeIDs []string
667700 disableMergeIDs []string
668- commentInput * IncidentCommentInput
669- responderInput * IncidentAddResponderInput
701+ commentInput * flashduty. IncidentCommentInput
702+ responderInput * flashduty. IncidentAddResponderInput
670703}
671704
672705func (m * mockIncidentLifecycle ) UnackIncidents (_ context.Context , incidentIDs []string ) error {
@@ -689,14 +722,14 @@ func (m *mockIncidentLifecycle) DisableIncidentMerge(_ context.Context, incident
689722 return nil
690723}
691724
692- func (m * mockIncidentLifecycle ) CommentIncidents (_ context.Context , input * IncidentCommentInput ) error {
725+ func (m * mockIncidentLifecycle ) CommentIncidents (_ context.Context , input * flashduty. IncidentCommentInput ) error {
693726 copied := * input
694727 copied .IncidentIDs = append ([]string (nil ), input .IncidentIDs ... )
695728 m .commentInput = & copied
696729 return nil
697730}
698731
699- func (m * mockIncidentLifecycle ) AddIncidentResponders (_ context.Context , input * IncidentAddResponderInput ) error {
732+ func (m * mockIncidentLifecycle ) AddIncidentResponders (_ context.Context , input * flashduty. IncidentAddResponderInput ) error {
700733 copied := * input
701734 copied .PersonIDs = append ([]int64 (nil ), input .PersonIDs ... )
702735 if input .Notify != nil {
@@ -907,56 +940,61 @@ func TestCommandIncidentDisableMerge(t *testing.T) {
907940type mockIncidentWarRoom struct {
908941 mockClient
909942
910- createInput * IncidentWarRoomCreateInput
911- listInput * IncidentWarRoomListInput
912- getInput * IncidentWarRoomDetailInput
913- deleteInput * IncidentWarRoomDeleteInput
914- addMemberInput * IncidentWarRoomAddMemberInput
943+ createInput * flashduty. IncidentWarRoomCreateInput
944+ listInput * flashduty. IncidentWarRoomListInput
945+ getInput * flashduty. IncidentWarRoomDetailInput
946+ deleteInput * flashduty. IncidentWarRoomDeleteInput
947+ addMemberInput * flashduty. IncidentWarRoomAddMemberInput
915948 defaultObserverIncID string
916- defaultObserverOutput []IncidentWarRoomObserver
949+ defaultObserverOutput []flashduty.IncidentWarRoomObserver
950+ enabledDataSources []flashduty.DataSourceIntegration
917951}
918952
919- func (m * mockIncidentWarRoom ) CreateIncidentWarRoom (_ context.Context , input * IncidentWarRoomCreateInput ) (* IncidentWarRoom , error ) {
953+ func (m * mockIncidentWarRoom ) CreateIncidentWarRoom (_ context.Context , input * flashduty. IncidentWarRoomCreateInput ) (* flashduty. IncidentWarRoom , error ) {
920954 copied := * input
921955 copied .MemberIDs = append ([]int64 (nil ), input .MemberIDs ... )
922956 m .createInput = & copied
923- return & IncidentWarRoom {ChatID : "chat-1" , ChatName : "INC outage" , ShareLink : "https://chat.example/1" }, nil
957+ return & flashduty. IncidentWarRoom {ChatID : "chat-1" , ChatName : "INC outage" , ShareLink : "https://chat.example/1" }, nil
924958}
925959
926- func (m * mockIncidentWarRoom ) ListIncidentWarRooms (_ context.Context , input * IncidentWarRoomListInput ) (* IncidentWarRoomListOutput , error ) {
960+ func (m * mockIncidentWarRoom ) ListIncidentWarRooms (_ context.Context , input * flashduty. IncidentWarRoomListInput ) (* flashduty. IncidentWarRoomListOutput , error ) {
927961 copied := * input
928962 m .listInput = & copied
929- return & IncidentWarRoomListOutput {
930- Items : []IncidentWarRoomItem {
963+ return & flashduty. IncidentWarRoomListOutput {
964+ Items : []flashduty. IncidentWarRoomItem {
931965 {IntegrationID : 42 , ChatID : "chat-1" , IncidentID : "inc-1" , Status : "enabled" , PluginType : "feishu" },
932966 },
933967 }, nil
934968}
935969
936- func (m * mockIncidentWarRoom ) GetIncidentWarRoom (_ context.Context , input * IncidentWarRoomDetailInput ) (* IncidentWarRoom , error ) {
970+ func (m * mockIncidentWarRoom ) GetIncidentWarRoom (_ context.Context , input * flashduty. IncidentWarRoomDetailInput ) (* flashduty. IncidentWarRoom , error ) {
937971 copied := * input
938972 m .getInput = & copied
939- return & IncidentWarRoom {ChatID : "chat-1" , ChatName : "INC outage" , ShareLink : "https://chat.example/1" }, nil
973+ return & flashduty. IncidentWarRoom {ChatID : "chat-1" , ChatName : "INC outage" , ShareLink : "https://chat.example/1" }, nil
940974}
941975
942- func (m * mockIncidentWarRoom ) DeleteIncidentWarRoom (_ context.Context , input * IncidentWarRoomDeleteInput ) error {
976+ func (m * mockIncidentWarRoom ) DeleteIncidentWarRoom (_ context.Context , input * flashduty. IncidentWarRoomDeleteInput ) error {
943977 copied := * input
944978 m .deleteInput = & copied
945979 return nil
946980}
947981
948- func (m * mockIncidentWarRoom ) AddIncidentWarRoomMembers (_ context.Context , input * IncidentWarRoomAddMemberInput ) error {
982+ func (m * mockIncidentWarRoom ) AddIncidentWarRoomMembers (_ context.Context , input * flashduty. IncidentWarRoomAddMemberInput ) error {
949983 copied := * input
950984 copied .MemberIDs = append ([]int64 (nil ), input .MemberIDs ... )
951985 m .addMemberInput = & copied
952986 return nil
953987}
954988
955- func (m * mockIncidentWarRoom ) GetIncidentWarRoomDefaultObservers (_ context.Context , incidentID string ) ([]IncidentWarRoomObserver , error ) {
989+ func (m * mockIncidentWarRoom ) GetIncidentWarRoomDefaultObservers (_ context.Context , incidentID string ) ([]flashduty. IncidentWarRoomObserver , error ) {
956990 m .defaultObserverIncID = incidentID
957991 return m .defaultObserverOutput , nil
958992}
959993
994+ func (m * mockIncidentWarRoom ) ListWarRoomEnabledDataSources (context.Context ) (* flashduty.ListWarRoomEnabledDataSourcesOutput , error ) {
995+ return & flashduty.ListWarRoomEnabledDataSourcesOutput {Items : m .enabledDataSources }, nil
996+ }
997+
960998func TestCommandIncidentWarRoomCreateWithObservers (t * testing.T ) {
961999 saveAndResetGlobals (t )
9621000 mock := & mockIncidentWarRoom {}
@@ -980,10 +1018,48 @@ func TestCommandIncidentWarRoomCreateWithObservers(t *testing.T) {
9801018 }
9811019}
9821020
1021+ func TestCommandIncidentWarRoomCreateAutoDiscoversIntegration (t * testing.T ) {
1022+ saveAndResetGlobals (t )
1023+ mock := & mockIncidentWarRoom {
1024+ enabledDataSources : []flashduty.DataSourceIntegration {
1025+ {DataSourceID : 42 , Name : "Feishu" , PluginType : "feishu_app" },
1026+ },
1027+ }
1028+ newClientFn = func () (flashdutyClient , error ) { return mock , nil }
1029+
1030+ out , err := execCommand ("incident" , "war-room" , "create" , "inc-1" , "--member" , "101" )
1031+ if err != nil {
1032+ t .Fatalf ("[incident-war-room-create-autodiscover] unexpected error: %v" , err )
1033+ }
1034+ if mock .createInput == nil {
1035+ t .Fatal ("[incident-war-room-create-autodiscover] expected CreateIncidentWarRoom to be called" )
1036+ }
1037+ if mock .createInput .IntegrationID != 42 {
1038+ t .Fatalf ("[incident-war-room-create-autodiscover] expected integration 42, got %#v" , mock .createInput )
1039+ }
1040+ if ! strings .Contains (out , "War room created: chat-1" ) {
1041+ t .Fatalf ("[incident-war-room-create-autodiscover] unexpected output:\n %s" , out )
1042+ }
1043+ }
1044+
1045+ func TestCommandIncidentWarRoomCreateRequiresEnabledIntegration (t * testing.T ) {
1046+ saveAndResetGlobals (t )
1047+ mock := & mockIncidentWarRoom {}
1048+ newClientFn = func () (flashdutyClient , error ) { return mock , nil }
1049+
1050+ _ , err := execCommand ("incident" , "war-room" , "create" , "inc-1" )
1051+ if err == nil || ! strings .Contains (err .Error (), "no IM integration has war-room enabled" ) {
1052+ t .Fatalf ("[incident-war-room-create-no-enabled-integration] expected enabled integration error, got %v" , err )
1053+ }
1054+ if mock .createInput != nil {
1055+ t .Fatalf ("[incident-war-room-create-no-enabled-integration] did not expect create call: %#v" , mock .createInput )
1056+ }
1057+ }
1058+
9831059func TestCommandIncidentWarRoomDefaultObservers (t * testing.T ) {
9841060 saveAndResetGlobals (t )
9851061 mock := & mockIncidentWarRoom {
986- defaultObserverOutput : []IncidentWarRoomObserver {
1062+ defaultObserverOutput : []flashduty. IncidentWarRoomObserver {
9871063 {PersonID : 101 , PersonName : "Alice" , Email : "alice@example.com" },
9881064 },
9891065 }
0 commit comments