import { DefaultTheme, ThemeProvider } from '@react-navigation/native' import { act, fireEvent, render } from '@testing-library/react-native' import React, { forwardRef, useImperativeHandle } from 'react' import { VideoAttachment } from '../../../../components/conversation/attachments/video_attachment' import { DenormalizedMessageAttachmentResource } from '../../../../types/resources/denormalized_attachment_resource' import { AudioAdapter, ChatAdapters, ClipboardAdapter, ImagePickerAdapter, VideoAdapter, } from '../../../../utils/native_adapters' import { VideoPlayerHandle, VideoPlayerProps } from '../../../../utils/native_adapters/video' const handle: VideoPlayerHandle = { play: jest.fn(), pause: jest.fn(), presentFullscreenPlayer: jest.fn(), dismissFullscreen: jest.fn(), } const playerRender = jest.fn() const Player = forwardRef((props, ref) => { playerRender(props) useImperativeHandle(ref, () => handle) return null }) function latestPlayerProps() { return playerRender.mock.calls.at(-1)?.[0] } const attachment: DenormalizedMessageAttachmentResource = { type: 'MessageAttachment', id: '1', attributes: { filename: 'clip.mp4', key: 'clip', contentType: 'video/mp4', byteSize: 1, checksum: 'abc', metadata: { width: 100, height: 100 }, url: 'https://example.com/clip.mp4', }, } describe('VideoAttachment', () => { beforeAll(() => { ChatAdapters.configure({ clipboard: new ClipboardAdapter({ getStringAsync: jest.fn(async () => ''), setStringAsync: jest.fn(async () => {}), }), audio: new AudioAdapter({ useAudio: () => ({ play: jest.fn(), pause: jest.fn(), isPlaying: false, duration: 0, position: 0, AudioPlayer: null, }), }), video: new VideoAdapter({ Player }), imagePicker: new ImagePickerAdapter({ openCameraAsync: async () => ({ canceled: true, assets: null }), openImageLibraryAsync: async () => ({ canceled: true, assets: null }), }), }) }) beforeEach(() => { jest.clearAllMocks() }) function renderAttachment() { return render( ) } it('opens fullscreen and plays once per open', () => { const { getByLabelText } = renderAttachment() fireEvent.press(getByLabelText('Play Video')) fireEvent.press(getByLabelText('Play Video')) expect(handle.presentFullscreenPlayer).toHaveBeenCalledTimes(1) expect(handle.play).toHaveBeenCalledTimes(1) }) it('pauses and can be reopened after the player dismisses fullscreen', () => { const { getByLabelText } = renderAttachment() fireEvent.press(getByLabelText('Play Video')) act(() => latestPlayerProps()?.onFullscreenDismiss()) expect(handle.pause).toHaveBeenCalledTimes(1) fireEvent.press(getByLabelText('Play Video')) expect(handle.presentFullscreenPlayer).toHaveBeenCalledTimes(2) }) })