import React from 'react' import { useChannelStateContext, useMessageContext } from 'stream-chat-react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { renderWithProviders, screen } from '../../test/utils' import { OutboundContext } from './OutboundContext' import { isTipMessage } from './TipMessage' import { CustomMessage } from './index' vi.mock('stream-chat-react', () => ({ Attachment: () => null, EditMessageModal: () => null, MessageBounceModal: () => null, MessageBouncePrompt: () => null, MessageBlocked: () => null, MessageDeleted: () => null, MessageErrorIcon: () => null, MessageIsThreadReplyInChannelButtonIndicator: () => null, MessageRepliesCountButton: () => null, MessageStatus: ({ MessageSentStatus, }: { MessageSentStatus: React.ComponentType }) => , MessageText: () => Message, Poll: () => null, ReminderNotification: () => null, StreamedMessageText: () => null, areMessageUIPropsEqual: () => true, isDateSeparatorMessage: () => false, isMessageBlocked: () => false, isMessageBounced: () => false, messageHasAttachments: () => false, messageHasReactions: () => false, useChannelStateContext: vi.fn(), useChatContext: () => ({ client: { polls: { fromState: vi.fn() } } }), useComponentContext: () => ({ Attachment: () => null, MessageRepliesCountButton: () => null, }), useMessageContext: vi.fn(), useMessageReminder: () => undefined, })) vi.mock('./context', () => ({ useCustomMessage: () => ({ isUnlocking: () => false, }), })) vi.mock('../Avatar', () => ({ Avatar: () => null, })) vi.mock('./MessageTag', () => ({ MessageTag: () => null, isAttachmentMessage: () => false, isChatbotMessage: () => false, isMediaAttachmentMessage: () => false, isPaidMessage: () => false, isTextAttachmentMessage: () => false, hasPaidDeliveryTag: () => false, })) vi.mock('./TipMessage', () => ({ TipMessage: () => null, isTipMessage: vi.fn(() => false), })) vi.mock('./LockedAttachment', () => ({ default: () => null, })) vi.mock('./StreamAttachmentMessage', () => ({ default: () => null, buildOrderedAttachmentSegments: () => [], })) vi.mock('../MediaMessage', () => ({ isLinkAttachment: () => false, })) const mockedUseChannelStateContext = vi.mocked(useChannelStateContext) const mockedUseMessageContext = vi.mocked(useMessageContext) const mockedIsTipMessage = vi.mocked(isTipMessage) describe('CustomMessage', () => { beforeEach(() => { mockedIsTipMessage.mockReturnValue(false) mockedUseChannelStateContext.mockReturnValue({ messages: [{ id: 'message-1', user: { id: 'me' } }], } as never) mockedUseMessageContext.mockReturnValue({ message: { id: 'message-1', text: 'Hello', type: 'regular', status: 'received', user: { id: 'me', name: 'Me' }, metadata: { outbound_id: 'outbound-1', }, }, isMyMessage: () => true, threadList: false, editing: false, endOfGroup: true, firstOfGroup: true, groupedByUser: true, handleAction: vi.fn(), handleOpenThread: vi.fn(), handleRetry: vi.fn(), highlighted: false, renderText: undefined, isMessageAIGenerated: undefined, } as never) }) it('uses the latest outbound click handler after rerendering', () => { const firstHandler = vi.fn() const secondHandler = vi.fn() const { rerender } = renderWithProviders( ) rerender( ) screen .getByRole('button', { name: 'View broadcast July 9th Class attendees', }) .click() expect(firstHandler).not.toHaveBeenCalled() expect(secondHandler).toHaveBeenCalledWith({ id: 'automation-1', name: 'July 9th Class attendees', }) }) it('renders the current source returned for the outbound id', () => { renderWithProviders( ) expect( screen.getByTestId('sent-message-outbound-status') ).toHaveTextContent('July 9th Class absentee') }) it('hides the label when the outbound record cannot be resolved', () => { renderWithProviders( ) expect( screen.queryByTestId('sent-message-outbound-status') ).not.toBeInTheDocument() }) it('renders an outbound source when its lookup later resolves', () => { const { rerender } = renderWithProviders( ) rerender( ) expect( screen.getByTestId('sent-message-outbound-status') ).toHaveTextContent('July 9th Class absentee') }) it('does not render an accompanying text bubble for a whitespace-only tip message', () => { mockedIsTipMessage.mockReturnValue(true) mockedUseMessageContext.mockReturnValue({ message: { id: 'message-1', text: ' \n ', type: 'regular', status: 'received', user: { id: 'me', name: 'Me' }, metadata: {}, }, isMyMessage: () => true, threadList: false, editing: false, endOfGroup: true, firstOfGroup: true, groupedByUser: true, handleAction: vi.fn(), handleOpenThread: vi.fn(), handleRetry: vi.fn(), highlighted: false, renderText: undefined, isMessageAIGenerated: undefined, } as never) renderWithProviders( ) expect(screen.queryByText('Message')).not.toBeInTheDocument() }) it('renders an accompanying text bubble for a tip message with real text', () => { mockedIsTipMessage.mockReturnValue(true) // Default mocked message.text ('Hello') from beforeEach. renderWithProviders( ) expect(screen.getByText('Message')).toBeInTheDocument() }) })