import React from 'react' import type { Attachment, LocalMessage } from 'stream-chat' import { describe, expect, it } from 'vitest' import { fireEvent, renderWithProviders, screen } from '../../test/utils' import StreamAttachmentMessage, { linkCaptionDuplicatesAttachmentUrl, linkCardPropsFromStreamAttachment, } from './StreamAttachmentMessage' const message = (attachments: Attachment[], text?: string): LocalMessage => ({ attachments, text }) as LocalMessage describe('linkCardPropsFromStreamAttachment', () => { it('uses the featured layout when a thumbnail is present', () => { expect( linkCardPropsFromStreamAttachment({ type: 'link', og_scrape_url: 'https://linktr.ee/someone', image_url: 'https://cdn.example.com/thumb.jpg', }).layout ).toBe('featured') }) it('optimizes Linktree-hosted thumbnails for messaging attachment renders', () => { expect( linkCardPropsFromStreamAttachment({ type: 'link', og_scrape_url: 'https://linktr.ee/someone', image_url: 'https://assets.linktr.ee/thumb.jpg', }).thumbnailUrl ).toBe( 'https://assets.linktr.ee/thumb.jpg?io=true&size=messaging-attachment-v1_0' ) }) it('uses the classic layout for a plain link with no thumbnail', () => { expect( linkCardPropsFromStreamAttachment({ type: 'link', og_scrape_url: 'https://linktr.ee/someone', }).layout ).toBe('classic') }) it('keeps the featured layout for a playable clip with no thumbnail so the player renders', () => { expect( linkCardPropsFromStreamAttachment({ type: 'link', og_scrape_url: 'https://linktr.ee/someone', asset_url: 'https://cdn.example.com/clip.mp3', mime_type: 'audio/mpeg', }).layout ).toBe('featured') }) }) describe('linkCaptionDuplicatesAttachmentUrl', () => { it('suppresses captions that are just the link plus punctuation', () => { expect( linkCaptionDuplicatesAttachmentUrl( 'https://tr.ee/abc !', 'https://tr.ee/abc' ) ).toBe(true) }) it('keeps captions that add emoji after the link', () => { expect( linkCaptionDuplicatesAttachmentUrl( 'https://tr.ee/abc 😎', 'https://tr.ee/abc' ) ).toBe(false) }) }) describe('StreamAttachmentMessage', () => { it('renders a sent link card and suppresses a URL-only caption', () => { renderWithProviders( ) expect(screen.getByRole('link', { name: /my linktree/i })).toHaveAttribute( 'href', 'https://linktr.ee/someone' ) expect(screen.queryByText('https://linktr.ee/someone !')).toBeNull() }) it('keeps an emoji-only caption instead of dropping it', () => { const { container } = renderWithProviders( ) // MessageText linkifies the URL (display text drops the scheme), so the // caption is split across a link node and trailing emoji text. const captionBubble = container.querySelector( '.str-chat__message-bubble:not([data-attachment-bubble])' ) expect(captionBubble).toHaveTextContent('linktr.ee/someone') expect(captionBubble).toHaveTextContent('😎') }) it('renders mixed link and media attachments in order', () => { const { container } = renderWithProviders( ) const link = screen.getByRole('link', { name: /my linktree/i }) const imageBubble = screen.getByTestId('image-attachment') expect(link.compareDocumentPosition(imageBubble)).toBe( Node.DOCUMENT_POSITION_FOLLOWING ) expect(container).toHaveTextContent('caption') }) it('optimizes Linktree-hosted image attachments for the channel bubble', () => { renderWithProviders( ) expect(screen.getByRole('img', { name: 'Vacation' })).toHaveAttribute( 'src', 'https://ugc.production.linktr.ee/photo.jpg?io=true&size=messaging-attachment-v1_0' ) }) it('optimizes Linktree-hosted video posters for the channel bubble', () => { renderWithProviders( ) // Video posters were the last media URL leaving here at full size — // four of them per 2×2 grid. expect( screen.getByTestId('video-attachment').querySelector('img') ).toHaveAttribute( 'src', 'https://ugc.production.linktr.ee/poster.jpg?io=true&size=messaging-attachment-v1_0' ) }) it('keeps the original image source in the viewer for channel image attachments', () => { renderWithProviders( ) fireEvent.click(screen.getByLabelText('Open image 1 of 1')) const viewer = screen.getByTestId('image-viewer') expect(viewer).toHaveAttribute('open') expect(viewer.querySelector('img')?.getAttribute('src')).toBe( 'https://ugc.production.linktr.ee/photo.jpg' ) }) it('renders the accompanying message text next to a link attachment', () => { const { container } = renderWithProviders( ) const bubbles = container.querySelectorAll('.str-chat__message-bubble') expect(bubbles).toHaveLength(2) expect(bubbles[0]).toHaveAttribute('data-attachment-bubble', 'true') expect(bubbles[1]).toHaveTextContent('you have to see this') }) it('renders the accompanying message text next to a media attachment', () => { const { container } = renderWithProviders( ) expect(container).toHaveTextContent('from the trip') expect( container.querySelector( '.str-chat__message-bubble:not([data-attachment-bubble])' ) ).toHaveTextContent('from the trip') }) })