github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/commands_test.go (about)

     1  package chat
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/keybase/client/go/kbtest"
     9  	"github.com/keybase/client/go/protocol/chat1"
    10  	"github.com/keybase/client/go/protocol/keybase1"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestChatCommands(t *testing.T) {
    15  	ctc := makeChatTestContext(t, "TestChatCommands", 2)
    16  	defer ctc.cleanup()
    17  	users := ctc.users()
    18  	useRemoteMock = false
    19  	defer func() { useRemoteMock = true }()
    20  	timeout := 20 * time.Second
    21  	checkMsgText := func(list *serverChatListener, text string) {
    22  		select {
    23  		case msg := <-list.newMessageRemote:
    24  			require.True(t, msg.Message.IsValid())
    25  			require.True(t, msg.Message.Valid().MessageBody.IsType(chat1.MessageType_TEXT))
    26  			require.Equal(t, text, msg.Message.Valid().MessageBody.Text().Body)
    27  		case <-time.After(timeout):
    28  			require.Fail(t, "no msg")
    29  		}
    30  	}
    31  	checkHeadline := func(list *serverChatListener, headline string) {
    32  		select {
    33  		case msg := <-list.newMessageRemote:
    34  			require.True(t, msg.Message.IsValid())
    35  			require.True(t, msg.Message.Valid().MessageBody.IsType(chat1.MessageType_HEADLINE))
    36  			require.Equal(t, "chat about some pointless stuff",
    37  				msg.Message.Valid().MessageBody.Headline().Headline)
    38  		case <-time.After(timeout):
    39  			require.Fail(t, "no msg")
    40  		}
    41  	}
    42  
    43  	ctx := ctc.as(t, users[0]).startCtx
    44  	ui := kbtest.NewChatUI()
    45  	listener0 := newServerChatListener()
    46  	listener1 := newServerChatListener()
    47  	ctc.as(t, users[0]).h.mockChatUI = ui
    48  	ctc.as(t, users[0]).h.G().NotifyRouter.AddListener(listener0)
    49  	ctc.as(t, users[1]).h.G().NotifyRouter.AddListener(listener1)
    50  	ctc.world.Tcs[users[0].Username].G.UIRouter = kbtest.NewMockUIRouter(ui)
    51  	ctc.world.Tcs[users[0].Username].ChatG.Syncer.(*Syncer).isConnected = true
    52  	ctc.world.Tcs[users[1].Username].ChatG.Syncer.(*Syncer).isConnected = true
    53  	impConv := mustCreateConversationForTest(t, ctc, users[0], chat1.TopicType_CHAT,
    54  		chat1.ConversationMembersType_IMPTEAMNATIVE)
    55  	mustCreateConversationForTest(t, ctc, users[0],
    56  		chat1.TopicType_CHAT, chat1.ConversationMembersType_IMPTEAMNATIVE, users[1])
    57  	teamConv := mustCreateConversationForTest(t, ctc, users[0], chat1.TopicType_CHAT,
    58  		chat1.ConversationMembersType_TEAM, users[1])
    59  	topicName := "mike"
    60  	ncres, err := ctc.as(t, users[0]).chatLocalHandler().NewConversationLocal(ctx,
    61  		chat1.NewConversationLocalArg{
    62  			TlfName:       teamConv.TlfName,
    63  			TopicName:     &topicName,
    64  			TopicType:     chat1.TopicType_CHAT,
    65  			TlfVisibility: keybase1.TLFVisibility_PRIVATE,
    66  			MembersType:   chat1.ConversationMembersType_TEAM,
    67  		})
    68  	require.NoError(t, err)
    69  	consumeNewMsgRemote(t, listener0, chat1.MessageType_JOIN)
    70  	consumeNewMsgRemote(t, listener0, chat1.MessageType_SYSTEM)
    71  	consumeNewMsgRemote(t, listener0, chat1.MessageType_SYSTEM)
    72  	consumeNewMsgRemote(t, listener1, chat1.MessageType_SYSTEM)
    73  	consumeNewMsgRemote(t, listener1, chat1.MessageType_SYSTEM)
    74  	_, err = ctc.as(t, users[1]).chatLocalHandler().JoinConversationByIDLocal(ctx, ncres.Conv.GetConvID())
    75  	require.NoError(t, err)
    76  	consumeNewMsgRemote(t, listener0, chat1.MessageType_JOIN)
    77  	consumeNewMsgRemote(t, listener1, chat1.MessageType_JOIN)
    78  
    79  	t.Log("test /shrug")
    80  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
    81  		Body: "/shrug whatever",
    82  	}))
    83  	checkMsgText(listener0, `whatever ¯\_(ツ)_/¯`)
    84  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
    85  		Body: "/shrug ",
    86  	}))
    87  	checkMsgText(listener0, `¯\_(ツ)_/¯`)
    88  
    89  	t.Logf("test /msg")
    90  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
    91  		Body: fmt.Sprintf("/msg %s hi", users[1].Username),
    92  	}))
    93  	checkMsgText(listener0, "hi")
    94  	checkMsgText(listener1, "hi")
    95  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
    96  		Body: fmt.Sprintf("/msg %s hi team", teamConv.TlfName),
    97  	}))
    98  	checkMsgText(listener0, "hi team")
    99  	checkMsgText(listener1, "hi team")
   100  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   101  		Body: fmt.Sprintf("/msg %s#%s hi channel", teamConv.TlfName, "mike"),
   102  	}))
   103  	checkMsgText(listener0, "hi channel")
   104  	checkMsgText(listener1, "hi channel")
   105  
   106  	t.Logf("test /me")
   107  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   108  		Body: "/me rises against the tide",
   109  	}))
   110  	checkMsgText(listener0, "_rises against the tide_")
   111  
   112  	t.Logf("test /headline")
   113  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   114  		Body: "/topic chat about some pointless stuff",
   115  	}))
   116  	checkHeadline(listener0, "/topic chat about some pointless stuff")
   117  	mustPostLocalForTest(t, ctc, users[0], teamConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   118  		Body: "/topic chat about some pointless stuff",
   119  	}))
   120  	checkHeadline(listener0, "/topic chat about some pointless stuff")
   121  	checkHeadline(listener1, "/topic chat about some pointless stuff")
   122  
   123  	testLeave := func() {
   124  		mustPostLocalForTest(t, ctc, users[0], ncres.Conv.Info,
   125  			chat1.NewMessageBodyWithText(chat1.MessageText{
   126  				Body: "/leave",
   127  			}))
   128  		consumeNewMsgRemote(t, listener1, chat1.MessageType_LEAVE)
   129  		select {
   130  		case convID := <-listener0.leftConv:
   131  			require.Equal(t, ncres.Conv.GetConvID(), convID)
   132  		case <-time.After(timeout):
   133  			require.Fail(t, "no leave")
   134  		}
   135  	}
   136  	t.Logf("test /join and /leave")
   137  	mustPostLocalForTest(t, ctc, users[0], teamConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   138  		Body: "/leave",
   139  	}))
   140  	checkMsgText(listener0, "/leave")
   141  	checkMsgText(listener1, "/leave")
   142  	testLeave()
   143  	mustPostLocalForTest(t, ctc, users[0], teamConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   144  		Body: "/join",
   145  	}))
   146  	select {
   147  	case <-ui.ShowManageChannels:
   148  	case <-time.After(timeout):
   149  		require.Fail(t, "no show")
   150  	}
   151  	_, err = ctc.as(t, users[0]).chatLocalHandler().JoinConversationLocal(ctx, chat1.JoinConversationLocalArg{
   152  		TlfName:    teamConv.TlfName,
   153  		TopicType:  chat1.TopicType_CHAT,
   154  		TopicName:  "mike",
   155  		Visibility: keybase1.TLFVisibility_PRIVATE,
   156  	})
   157  	require.NoError(t, err)
   158  	consumeNewMsgRemote(t, listener0, chat1.MessageType_JOIN)
   159  	consumeNewMsgRemote(t, listener1, chat1.MessageType_JOIN)
   160  	testLeave()
   161  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   162  		Body: fmt.Sprintf("/join %s#mike", teamConv.TlfName),
   163  	}))
   164  	checkMsgText(listener0, fmt.Sprintf("/join %s#mike", teamConv.TlfName))
   165  
   166  	t.Logf("test /hide and /unhide")
   167  	mustPostLocalForTest(t, ctc, users[0], teamConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   168  		Body: fmt.Sprintf("/hide %s", users[0].Username),
   169  	}))
   170  	select {
   171  	case info := <-listener0.setStatus:
   172  		require.Equal(t, impConv.Id, info.ConvID)
   173  		require.Equal(t, chat1.ConversationStatus_IGNORED, info.Status)
   174  	case <-time.After(timeout):
   175  		require.Fail(t, "no set status")
   176  	}
   177  	mustPostLocalForTest(t, ctc, users[0], teamConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   178  		Body: fmt.Sprintf("/unhide %s", users[0].Username),
   179  	}))
   180  	select {
   181  	case info := <-listener0.setStatus:
   182  		require.Equal(t, impConv.Id, info.ConvID)
   183  		require.Equal(t, chat1.ConversationStatus_UNFILED, info.Status)
   184  	case <-time.After(timeout):
   185  		require.Fail(t, "no set status")
   186  	}
   187  	mustPostLocalForTest(t, ctc, users[0], impConv, chat1.NewMessageBodyWithText(chat1.MessageText{
   188  		Body: "/hide",
   189  	}))
   190  	select {
   191  	case info := <-listener0.setStatus:
   192  		require.Equal(t, impConv.Id, info.ConvID)
   193  		require.Equal(t, chat1.ConversationStatus_IGNORED, info.Status)
   194  	case <-time.After(timeout):
   195  		require.Fail(t, "no set status")
   196  	}
   197  }