diff --git a/src/components/MediaRecorder/classes/MediaRecorderController.ts b/src/components/MediaRecorder/classes/MediaRecorderController.ts index 7b7c804db9..684e5687d6 100644 --- a/src/components/MediaRecorder/classes/MediaRecorderController.ts +++ b/src/components/MediaRecorder/classes/MediaRecorderController.ts @@ -17,25 +17,18 @@ import { } from '../../ReactFileUtilities'; import { TranslationContextValue } from '../../../context'; import { defaultTranslatorFunction } from '../../../i18n'; -import { isSafari } from '../../../utils/browsers'; import { mergeDeepUndefined } from '../../../utils/mergeDeep'; import type { LocalVoiceRecordingAttachment } from '../../MessageInput'; import type { DefaultStreamChatGenerics } from '../../../types'; -const RECORDED_MIME_TYPE_BY_BROWSER = { +export const RECORDED_MIME_TYPE_BY_BROWSER = { audio: { others: 'audio/webm', safari: 'audio/mp4;codecs=mp4a.40.2', }, } as const; -export const DEFAULT_MEDIA_RECORDER_CONFIG: MediaRecorderConfig = { - mimeType: isSafari() - ? RECORDED_MIME_TYPE_BY_BROWSER.audio.safari - : RECORDED_MIME_TYPE_BY_BROWSER.audio.others, -} as const; - export const DEFAULT_AUDIO_TRANSCODER_CONFIG: TranscoderConfig = { sampleRate: 16000, } as const; @@ -120,7 +113,11 @@ export class MediaRecorderController< this.mediaRecorderConfig = mergeDeepUndefined( { ...config?.mediaRecorderConfig }, - DEFAULT_MEDIA_RECORDER_CONFIG, + { + mimeType: MediaRecorder.isTypeSupported('audio/webm') + ? RECORDED_MIME_TYPE_BY_BROWSER.audio.others + : RECORDED_MIME_TYPE_BY_BROWSER.audio.safari, + }, ); this.transcoderConfig = mergeDeepUndefined( diff --git a/src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.js b/src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.js index 7d20432acd..27cafb2ca2 100644 --- a/src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.js +++ b/src/components/MediaRecorder/classes/__tests__/MediaRecorderController.test.js @@ -3,9 +3,9 @@ import * as transcoder from '../../transcode'; import * as wavTranscoder from '../../transcode/wav'; import { DEFAULT_AUDIO_TRANSCODER_CONFIG, - DEFAULT_MEDIA_RECORDER_CONFIG, MediaRecorderController, MediaRecordingState, + RECORDED_MIME_TYPE_BY_BROWSER, RecordingAttachmentType, } from '../MediaRecorderController'; import { @@ -92,10 +92,27 @@ describe('MediaRecorderController', () => { }); afterEach(jest.clearAllMocks); - it('provides defaults on initiation', () => { + it('provides defaults on initiation (non-Safari)', () => { const controller = new MediaRecorderController(); expect(controller.mediaRecorderConfig).toStrictEqual( - expect.objectContaining(DEFAULT_MEDIA_RECORDER_CONFIG), + expect.objectContaining({ mimeType: RECORDED_MIME_TYPE_BY_BROWSER.audio.others }), + ); + expect(controller.transcoderConfig).toStrictEqual( + expect.objectContaining(DEFAULT_AUDIO_TRANSCODER_CONFIG), + ); + expect(controller.amplitudeRecorderConfig).toStrictEqual( + expect.objectContaining(DEFAULT_AMPLITUDE_RECORDER_CONFIG), + ); + expect(controller.t).toStrictEqual(defaultTranslatorFunction); + expect(controller.mediaType).toStrictEqual('audio'); + expect(controller.customGenerateRecordingTitle).toBeUndefined(); + }); + + it('provides defaults on initiation (Safari)', () => { + MediaRecorder.isTypeSupported.mockReturnValueOnce(false); + const controller = new MediaRecorderController(); + expect(controller.mediaRecorderConfig).toStrictEqual( + expect.objectContaining({ mimeType: RECORDED_MIME_TYPE_BY_BROWSER.audio.safari }), ); expect(controller.transcoderConfig).toStrictEqual( expect.objectContaining(DEFAULT_AUDIO_TRANSCODER_CONFIG), @@ -151,7 +168,7 @@ describe('MediaRecorderController', () => { const controller = new MediaRecorderController({ generateRecordingTitle }); expect(controller.customGenerateRecordingTitle).toStrictEqual(generateRecordingTitle); expect(controller.mediaRecorderConfig).toStrictEqual( - expect.objectContaining(DEFAULT_MEDIA_RECORDER_CONFIG), + expect.objectContaining({ mimeType: RECORDED_MIME_TYPE_BY_BROWSER.audio.others }), ); expect(controller.transcoderConfig).toStrictEqual( expect.objectContaining(DEFAULT_AUDIO_TRANSCODER_CONFIG), diff --git a/src/components/MediaRecorder/hooks/__tests__/useMediaRecorder.test.js b/src/components/MediaRecorder/hooks/__tests__/useMediaRecorder.test.js index 4cfbfba97b..b68849e3a0 100644 --- a/src/components/MediaRecorder/hooks/__tests__/useMediaRecorder.test.js +++ b/src/components/MediaRecorder/hooks/__tests__/useMediaRecorder.test.js @@ -2,12 +2,14 @@ import { TranslationProvider } from '../../../../context'; import { renderHook } from '@testing-library/react'; import React from 'react'; import { useMediaRecorder } from '../useMediaRecorder'; -import { EventEmitterMock } from '../../../../mock-builders/browser'; +import { EventEmitterMock, MediaRecorderMock } from '../../../../mock-builders/browser'; import { act } from '@testing-library/react'; import { DEFAULT_AMPLITUDE_RECORDER_CONFIG } from '../../classes/AmplitudeRecorder'; import { DEFAULT_AUDIO_TRANSCODER_CONFIG } from '../../classes'; import { generateVoiceRecordingAttachment } from '../../../../mock-builders'; +window.MediaRecorder = MediaRecorderMock; + const handleSubmit = jest.fn(); const uploadAttachment = jest.fn(); @@ -27,8 +29,8 @@ const render = async (params = {}) => { {children} ); let result; - await act(() => { - result = renderHook(() => useMediaRecorder({ enabled: true, ...params }), { + await act(async () => { + result = await renderHook(() => useMediaRecorder({ enabled: true, ...params }), { wrapper, }); }); diff --git a/src/mock-builders/browser/MediaRecorder.js b/src/mock-builders/browser/MediaRecorder.js index 95906b3c75..55167da41b 100644 --- a/src/mock-builders/browser/MediaRecorder.js +++ b/src/mock-builders/browser/MediaRecorder.js @@ -3,10 +3,11 @@ import { EventEmitterMock } from './EventEmitter'; export class MediaRecorderMock extends EventEmitterMock { constructor() { super(); + this.start = jest.fn(); + this.pause = jest.fn(); + this.resume = jest.fn(); + this.stop = jest.fn(); } - start = jest.fn(); - pause = jest.fn(); - resume = jest.fn(); - stop = jest.fn(); + static isTypeSupported = jest.fn().mockReturnValue(true); }