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

     1  package chat
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/keybase/client/go/protocol/chat1"
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func TestChatReplyToBasic(t *testing.T) {
    12  	runWithMemberTypes(t, func(mt chat1.ConversationMembersType) {
    13  		ctc := makeChatTestContext(t, "ChatReplyTo", 1)
    14  		defer ctc.cleanup()
    15  		users := ctc.users()
    16  
    17  		ctx := ctc.as(t, users[0]).startCtx
    18  		timeout := 20 * time.Second
    19  		listener0 := newServerChatListener()
    20  		ctc.as(t, users[0]).h.G().NotifyRouter.AddListener(listener0)
    21  		t.Logf("uid0: %s", users[0].GetUID())
    22  
    23  		conv := mustCreateConversationForTest(t, ctc, users[0], chat1.TopicType_CHAT, mt)
    24  		consumeNewConversation(t, listener0, conv.Id)
    25  
    26  		origID := mustPostLocalForTest(t, ctc, users[0], conv,
    27  			chat1.NewMessageBodyWithText(chat1.MessageText{
    28  				Body: "MIKE",
    29  			}))
    30  		consumeNewMsgRemote(t, listener0, chat1.MessageType_TEXT)
    31  		consumeNewMsgLocal(t, listener0, chat1.MessageType_TEXT)
    32  
    33  		// reply
    34  		t.Logf("send reply")
    35  		postRes, err := ctc.as(t, users[0]).chatLocalHandler().PostLocal(ctx, chat1.PostLocalArg{
    36  			ConversationID: conv.Id,
    37  			Msg: chat1.MessagePlaintext{
    38  				ClientHeader: chat1.MessageClientHeader{
    39  					Conv:        conv.Triple,
    40  					MessageType: chat1.MessageType_TEXT,
    41  					TlfName:     conv.TlfName,
    42  				},
    43  				MessageBody: chat1.NewMessageBodyWithText(chat1.MessageText{
    44  					Body: "REPLY",
    45  				}),
    46  			},
    47  			ReplyTo: &origID,
    48  		})
    49  		require.NoError(t, err)
    50  
    51  		// Check that we get the reply on notifications and fetches
    52  		select {
    53  		case note := <-listener0.newMessageLocal:
    54  			require.True(t, note.Message.IsValid())
    55  			require.NotNil(t, note.Message.Valid().ReplyTo)
    56  			require.Equal(t, origID, note.Message.Valid().ReplyTo.GetMessageID())
    57  		case <-time.After(timeout):
    58  			require.Fail(t, "no local")
    59  		}
    60  		select {
    61  		case note := <-listener0.newMessageRemote:
    62  			require.True(t, note.Message.IsValid())
    63  			require.NotNil(t, note.Message.Valid().ReplyTo)
    64  			require.Equal(t, origID, note.Message.Valid().ReplyTo.GetMessageID())
    65  		case <-time.After(timeout):
    66  			require.Fail(t, "no local")
    67  		}
    68  		threadRes, err := ctc.as(t, users[0]).chatLocalHandler().GetThreadLocal(ctx, chat1.GetThreadLocalArg{
    69  			ConversationID: conv.Id,
    70  			Query: &chat1.GetThreadQuery{
    71  				MessageTypes: []chat1.MessageType{chat1.MessageType_TEXT},
    72  			},
    73  		})
    74  		require.NoError(t, err)
    75  		require.Equal(t, 2, len(threadRes.Thread.Messages))
    76  		require.True(t, threadRes.Thread.Messages[0].IsValid())
    77  		require.NotNil(t, threadRes.Thread.Messages[0].Valid().ReplyTo)
    78  		require.Equal(t, origID, threadRes.Thread.Messages[0].Valid().ReplyTo.GetMessageID())
    79  
    80  		t.Logf("edit original message")
    81  		mustEditMsg(ctx, t, ctc, users[0], conv, origID)
    82  		consumeNewMsgRemote(t, listener0, chat1.MessageType_EDIT)
    83  		consumeNewMsgLocal(t, listener0, chat1.MessageType_EDIT)
    84  		for i := 0; i < 2; i++ {
    85  			select {
    86  			case update := <-listener0.messagesUpdated:
    87  				require.Equal(t, 1, len(update.Updates))
    88  				require.Equal(t, postRes.MessageID, update.Updates[0].GetMessageID())
    89  				require.True(t, update.Updates[0].IsValid())
    90  				require.NotNil(t, update.Updates[0].Valid().ReplyTo)
    91  				require.True(t, update.Updates[0].Valid().ReplyTo.IsValid())
    92  				require.Equal(t, "edited", update.Updates[0].Valid().ReplyTo.Valid().BodySummary)
    93  			case <-time.After(timeout):
    94  				require.Fail(t, "no message update")
    95  			}
    96  		}
    97  
    98  		t.Logf("delete original message")
    99  		mustDeleteMsg(ctx, t, ctc, users[0], conv, origID)
   100  		consumeNewMsgRemote(t, listener0, chat1.MessageType_DELETE)
   101  		consumeNewMsgLocal(t, listener0, chat1.MessageType_DELETE)
   102  		select {
   103  		case update := <-listener0.messagesUpdated:
   104  			require.Equal(t, 1, len(update.Updates))
   105  			require.Equal(t, postRes.MessageID, update.Updates[0].GetMessageID())
   106  			require.True(t, update.Updates[0].IsValid())
   107  			require.NotNil(t, update.Updates[0].Valid().ReplyTo)
   108  			st, err := update.Updates[0].Valid().ReplyTo.State()
   109  			require.NoError(t, err)
   110  			require.Equal(t, chat1.MessageUnboxedState_PLACEHOLDER, st)
   111  		case <-time.After(timeout):
   112  			require.Fail(t, "no message update")
   113  		}
   114  	})
   115  }