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

     1  package chat
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/keybase/client/go/chat/globals"
     8  	"github.com/keybase/client/go/kbtest"
     9  	"github.com/keybase/client/go/protocol/chat1"
    10  	"github.com/keybase/client/go/protocol/gregor1"
    11  	"github.com/keybase/client/go/protocol/keybase1"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestTeamChannelSource(t *testing.T) {
    16  	runWithMemberTypes(t, func(mt chat1.ConversationMembersType) {
    17  		// Only run this test for teams
    18  		switch mt {
    19  		case chat1.ConversationMembersType_TEAM:
    20  		default:
    21  			return
    22  		}
    23  
    24  		ctc := makeChatTestContext(t, "TestTeamChannelSource", 2)
    25  		defer ctc.cleanup()
    26  		users := ctc.users()
    27  
    28  		ctx1 := ctc.as(t, users[0]).startCtx
    29  		// ctx2 := ctc.as(t, users[1]).startCtx
    30  		listener1 := newServerChatListener()
    31  		ctc.as(t, users[0]).h.G().NotifyRouter.AddListener(listener1)
    32  		listener2 := newServerChatListener()
    33  		ctc.as(t, users[1]).h.G().NotifyRouter.AddListener(listener2)
    34  		ui := kbtest.NewChatUI()
    35  		ctc.as(t, users[0]).h.mockChatUI = ui
    36  		ctc.as(t, users[1]).h.mockChatUI = ui
    37  		ctc.world.Tcs[users[0].Username].ChatG.Syncer.(*Syncer).isConnected = true
    38  		ctc.world.Tcs[users[1].Username].ChatG.Syncer.(*Syncer).isConnected = true
    39  		uid1 := users[0].User.GetUID().ToBytes()
    40  		g1 := ctc.world.Tcs[users[0].Username].Context()
    41  		uid2 := users[1].User.GetUID().ToBytes()
    42  		g2 := ctc.world.Tcs[users[1].Username].Context()
    43  		t.Logf("uid1: %v, uid2: %v", users[0].User.GetUID(), users[1].User.GetUID())
    44  
    45  		var tlfID chat1.TLFID
    46  		ctx := context.TODO()
    47  
    48  		type expectedResult struct {
    49  			ConvID       chat1.ConversationID
    50  			Existence    chat1.ConversationExistence
    51  			MemberStatus chat1.ConversationMemberStatus
    52  			TopicName    string
    53  		}
    54  
    55  		// Verify all public functions of the team channel source return the expected results.
    56  		assertTeamChannelSource := func(g *globals.Context, uid gregor1.UID, expectedResults map[chat1.ConvIDStr]expectedResult) {
    57  			convs, err := g.TeamChannelSource.GetChannelsFull(ctx, uid, tlfID, chat1.TopicType_CHAT)
    58  			require.NoError(t, err)
    59  			require.Equal(t, len(expectedResults), len(convs))
    60  			for _, conv := range convs {
    61  				expected, ok := expectedResults[conv.GetConvID().ConvIDStr()]
    62  				require.True(t, ok)
    63  				require.Equal(t, expected.ConvID, conv.GetConvID())
    64  				require.Equal(t, expected.Existence, conv.Info.Existence)
    65  				require.Equal(t, expected.MemberStatus, conv.Info.MemberStatus)
    66  			}
    67  
    68  			mentions, err := g.TeamChannelSource.GetChannelsTopicName(ctx, uid, tlfID, chat1.TopicType_CHAT)
    69  			require.NoError(t, err)
    70  			require.Equal(t, len(expectedResults), len(mentions))
    71  			for _, mention := range mentions {
    72  				expected, ok := expectedResults[mention.ConvID.ConvIDStr()]
    73  				require.True(t, ok)
    74  				require.Equal(t, expected.ConvID, mention.ConvID)
    75  				require.Equal(t, expected.TopicName, mention.TopicName)
    76  			}
    77  
    78  			for _, expected := range expectedResults {
    79  				topicName, err := g.TeamChannelSource.GetChannelTopicName(ctx, uid, tlfID,
    80  					chat1.TopicType_CHAT, expected.ConvID)
    81  				require.NoError(t, err)
    82  				require.Equal(t, expected.TopicName, topicName)
    83  			}
    84  		}
    85  		assertTeamChannelSource(g1, uid1, nil)
    86  		assertTeamChannelSource(g2, uid2, nil)
    87  
    88  		conv := mustCreateConversationForTest(t, ctc, users[0], chat1.TopicType_CHAT, mt,
    89  			ctc.as(t, users[1]).user())
    90  		consumeNewConversation(t, listener1, conv.Id)
    91  		consumeNewConversation(t, listener2, conv.Id)
    92  		tlfID = conv.Triple.Tlfid
    93  		generalChannel := expectedResult{
    94  			ConvID:       conv.Id,
    95  			Existence:    chat1.ConversationExistence_ACTIVE,
    96  			MemberStatus: chat1.ConversationMemberStatus_ACTIVE,
    97  			TopicName:    "general",
    98  		}
    99  		// Both members can see the #general channel and are ACTIVE
   100  		expectedResults1 := map[chat1.ConvIDStr]expectedResult{conv.Id.ConvIDStr(): generalChannel}
   101  		expectedResults2 := map[chat1.ConvIDStr]expectedResult{conv.Id.ConvIDStr(): generalChannel}
   102  		assertTeamChannelSource(g1, uid1, expectedResults1)
   103  		assertTeamChannelSource(g2, uid2, expectedResults2)
   104  
   105  		topicName := "channel1"
   106  		channel1, err := ctc.as(t, users[0]).chatLocalHandler().NewConversationLocal(ctx,
   107  			chat1.NewConversationLocalArg{
   108  				TlfName:       conv.TlfName,
   109  				TopicName:     &topicName,
   110  				TopicType:     chat1.TopicType_CHAT,
   111  				TlfVisibility: keybase1.TLFVisibility_PRIVATE,
   112  				MembersType:   chat1.ConversationMembersType_TEAM,
   113  			})
   114  		require.NoError(t, err)
   115  		channelConvID := channel1.Conv.GetConvID()
   116  		consumeNewConversation(t, listener1, channelConvID)
   117  		assertNoNewConversation(t, listener2)
   118  		consumeNewMsgRemote(t, listener1, chat1.MessageType_JOIN)
   119  		consumeTeamType(t, listener1)
   120  		consumeTeamType(t, listener2)
   121  		consumeNewMsgRemote(t, listener1, chat1.MessageType_SYSTEM)
   122  		consumeNewMsgRemote(t, listener1, chat1.MessageType_SYSTEM)
   123  		consumeNewMsgRemote(t, listener2, chat1.MessageType_SYSTEM)
   124  		consumeNewMsgRemote(t, listener2, chat1.MessageType_SYSTEM)
   125  		t.Logf("created %v", topicName)
   126  
   127  		// Both members can see the #general channel and are ACTIVE
   128  		channel1User1 := expectedResult{
   129  			ConvID:       channelConvID,
   130  			Existence:    chat1.ConversationExistence_ACTIVE,
   131  			MemberStatus: chat1.ConversationMemberStatus_ACTIVE,
   132  			TopicName:    topicName,
   133  		}
   134  		expectedResults1[channelConvID.ConvIDStr()] = channel1User1
   135  
   136  		channel1User2 := expectedResult{
   137  			ConvID:       channelConvID,
   138  			Existence:    chat1.ConversationExistence_ACTIVE,
   139  			MemberStatus: chat1.ConversationMemberStatus_NEVER_JOINED,
   140  			TopicName:    topicName,
   141  		}
   142  		expectedResults2[channelConvID.ConvIDStr()] = channel1User2
   143  		assertTeamChannelSource(g1, uid1, expectedResults1)
   144  		assertTeamChannelSource(g2, uid2, expectedResults2)
   145  
   146  		// test rename
   147  		topicName = "channel1-renamed"
   148  		marg := chat1.PostMetadataNonblockArg{
   149  			ConversationID: channelConvID,
   150  			TlfName:        conv.TlfName,
   151  			TlfPublic:      false,
   152  			ChannelName:    topicName,
   153  		}
   154  		_, err = ctc.as(t, users[0]).chatLocalHandler().PostMetadataNonblock(ctx1, marg)
   155  		require.NoError(t, err)
   156  		consumeNewMsgRemote(t, listener1, chat1.MessageType_METADATA)
   157  		consumeNewMsgRemote(t, listener2, chat1.MessageType_METADATA)
   158  		t.Logf("renamed %v", topicName)
   159  
   160  		channel1User1.TopicName = topicName
   161  		channel1User2.TopicName = topicName
   162  		expectedResults1[channelConvID.ConvIDStr()] = channel1User1
   163  		expectedResults2[channelConvID.ConvIDStr()] = channel1User2
   164  		assertTeamChannelSource(g1, uid1, expectedResults1)
   165  		assertTeamChannelSource(g2, uid2, expectedResults2)
   166  
   167  		channel1User2.MemberStatus = chat1.ConversationMemberStatus_ACTIVE
   168  		expectedResults2[channelConvID.ConvIDStr()] = channel1User2
   169  		_, err = ctc.as(t, users[1]).chatLocalHandler().JoinConversationLocal(ctx1, chat1.JoinConversationLocalArg{
   170  			TlfName:    conv.TlfName,
   171  			TopicType:  chat1.TopicType_CHAT,
   172  			Visibility: keybase1.TLFVisibility_PRIVATE,
   173  			TopicName:  topicName,
   174  		})
   175  		require.NoError(t, err)
   176  		consumeNewMsgRemote(t, listener1, chat1.MessageType_JOIN)
   177  		consumeNewMsgRemote(t, listener2, chat1.MessageType_JOIN)
   178  		assertTeamChannelSource(g1, uid1, expectedResults1)
   179  		assertTeamChannelSource(g2, uid2, expectedResults2)
   180  
   181  		_, err = ctc.as(t, users[0]).chatLocalHandler().DeleteConversationLocal(ctx1,
   182  			chat1.DeleteConversationLocalArg{
   183  				ConvID: channelConvID,
   184  			})
   185  		require.NoError(t, err)
   186  		consumeLeaveConv(t, listener1)
   187  		consumeTeamType(t, listener1)
   188  		delete(expectedResults1, channelConvID.ConvIDStr())
   189  		delete(expectedResults2, channelConvID.ConvIDStr())
   190  		assertTeamChannelSource(g1, uid1, expectedResults1)
   191  		assertTeamChannelSource(g2, uid2, expectedResults2)
   192  
   193  		updates := consumeNewThreadsStale(t, listener1)
   194  		require.Equal(t, 1, len(updates))
   195  		require.Equal(t, channelConvID, updates[0].ConvID, "wrong cid")
   196  		require.Equal(t, chat1.StaleUpdateType_CLEAR, updates[0].UpdateType)
   197  
   198  		updates = consumeNewThreadsStale(t, listener2)
   199  		require.Equal(t, 1, len(updates))
   200  		require.Equal(t, channelConvID, updates[0].ConvID, "wrong cid")
   201  		require.Equal(t, chat1.StaleUpdateType_CLEAR, updates[0].UpdateType)
   202  	})
   203  }