import 'package:flutter_test/flutter_test.dart'; import 'package:tencent_rtc_sdk/trtc_cloud_def.dart'; import 'package:tencent_rtc_sdk/trtc_cloud_listener.dart'; import 'package:tencent_rtc_sdk/tx_audio_effect_manager.dart'; import 'package:yumi/services/audio/room_rtc_engine_adapter.dart'; import 'package:yumi/services/audio/room_rtc_types.dart'; import 'package:yumi/services/audio/trtc_room_rtc_engine_adapter.dart'; void main() { test('enters TRTC voice room with strRoomId and business userId', () async { final cloud = _FakeTrtcCloud(); final adapter = TrtcRoomRtcEngineAdapter(cloudFactory: () async => cloud); await adapter.enterRoomAsAudience( const RoomRtcEnterRoomConfig( identity: RoomRtcSessionIdentity( businessRoomId: 'business-room', trtcStrRoomId: 'room-account', trtcUserId: 'user-id', ), trtcSdkAppId: 20036101, trtcUserSig: 'sig', throwOnError: true, ), ); expect(cloud.enteredParams?.sdkAppId, 20036101); expect(cloud.enteredParams?.roomId, 0); expect(cloud.enteredParams?.strRoomId, 'room-account'); expect(cloud.enteredParams?.userId, 'user-id'); expect(cloud.enteredParams?.userSig, 'sig'); expect(cloud.enteredParams?.role, TRTCRoleType.audience); expect(cloud.enteredScene, TRTCAppScene.voiceChatRoom); expect(cloud.autoRecvAudio, isTrue); expect(cloud.autoRecvVideo, isFalse); expect(cloud.volumeEvaluationEnabled, isTrue); }); test('switches between anchor and audience with local audio state', () async { final cloud = _FakeTrtcCloud(); final adapter = TrtcRoomRtcEngineAdapter(cloudFactory: () async => cloud); await _enter(adapter); expect( await adapter.switchToAnchor(const RoomRtcAnchorConfig(muted: true)), isTrue, ); expect(cloud.lastRole, TRTCRoleType.anchor); expect(cloud.localAudioStarted, isTrue); expect(cloud.localAudioMuted, isTrue); expect(await adapter.switchToAudience(), isTrue); expect(cloud.lastRole, TRTCRoleType.audience); expect(cloud.localAudioStopped, isTrue); expect(cloud.localAudioMuted, isTrue); }); test('maps TRTC music calls to AudioEffectManager', () async { final cloud = _FakeTrtcCloud(); final adapter = TrtcRoomRtcEngineAdapter(cloudFactory: () async => cloud); final states = []; final musicAdapter = TrtcRoomRtcEngineAdapter( cloudFactory: () async => cloud, onAudioMixingStateChanged: (state, _) => states.add(state), ); await _enter(adapter); await _enter(musicAdapter); await musicAdapter.startAudioMixing( const RoomRtcAudioMixingConfig( filePath: '/tmp/a.mp3', loopback: false, cycle: 3, startPos: 1200, ), ); final musicParam = cloud.audioEffectManager.startedMusicParam!; expect(musicParam.id, 1); expect(musicParam.path, '/tmp/a.mp3'); expect(musicParam.publish, isTrue); expect(musicParam.loopCount, 2); expect(musicParam.startTimeMS, 1200); expect(states, contains(RoomRtcAudioMixingState.playing)); await musicAdapter.pauseAudioMixing(); await musicAdapter.resumeAudioMixing(); await musicAdapter.setAudioMixingVolume(80); expect(cloud.audioEffectManager.pausedIds, contains(1)); expect(cloud.audioEffectManager.resumedIds, contains(1)); expect(cloud.audioEffectManager.playoutVolume, 80); expect(cloud.audioEffectManager.publishVolume, 80); }); } Future _enter(TrtcRoomRtcEngineAdapter adapter) { return adapter.enterRoomAsAudience( const RoomRtcEnterRoomConfig( identity: RoomRtcSessionIdentity( businessRoomId: 'business-room', trtcStrRoomId: 'room-account', trtcUserId: 'user-id', ), trtcSdkAppId: 20036101, trtcUserSig: 'sig', throwOnError: true, ), ); } class _FakeTrtcCloud implements RoomTrtcCloud { final _FakeAudioEffectManager audioEffectManager = _FakeAudioEffectManager(); TRTCCloudListener? listener; TRTCParams? enteredParams; TRTCAppScene? enteredScene; TRTCRoleType? lastRole; bool? autoRecvAudio; bool? autoRecvVideo; bool volumeEvaluationEnabled = false; bool localAudioStarted = false; bool localAudioStopped = false; bool localAudioMuted = false; @override void registerListener(TRTCCloudListener listener) { this.listener = listener; } @override void unRegisterListener(TRTCCloudListener listener) { if (this.listener == listener) { this.listener = null; } } @override void setDefaultStreamRecvMode(bool autoRecvAudio, bool autoRecvVideo) { this.autoRecvAudio = autoRecvAudio; this.autoRecvVideo = autoRecvVideo; } @override void enableAudioVolumeEvaluation( bool enable, TRTCAudioVolumeEvaluateParams params, ) { volumeEvaluationEnabled = enable; } @override void enterRoom(TRTCParams param, TRTCAppScene scene) { enteredParams = param; enteredScene = scene; listener?.onEnterRoom?.call(10); } @override void exitRoom() { listener?.onExitRoom?.call(0); } @override void switchRole(TRTCRoleType role) { lastRole = role; } @override void startLocalAudio(TRTCAudioQuality quality) { localAudioStarted = true; } @override void stopLocalAudio() { localAudioStopped = true; } @override void muteLocalAudio(bool mute) { localAudioMuted = mute; } @override void muteAllRemoteAudio(bool mute) {} @override RoomTrtcAudioEffectManager getAudioEffectManager() { return audioEffectManager; } } class _FakeAudioEffectManager implements RoomTrtcAudioEffectManager { TXMusicPlayObserver? observer; AudioMusicParam? startedMusicParam; final pausedIds = []; final resumedIds = []; int? playoutVolume; int? publishVolume; int position = 0; @override void setMusicObserver(int musicId, TXMusicPlayObserver? observer) { this.observer = observer; } @override void startPlayMusic(AudioMusicParam musicParam) { startedMusicParam = musicParam; observer?.onStart(musicParam.id, 0); } @override void stopPlayMusic(int id) {} @override void pausePlayMusic(int id) { pausedIds.add(id); } @override void resumePlayMusic(int id) { resumedIds.add(id); } @override void setMusicPublishVolume(int id, int volume) { publishVolume = volume; } @override void setMusicPlayoutVolume(int id, int volume) { playoutVolume = volume; } @override int getMusicCurrentPosInMS(int id) { return position; } @override int getMusicDurationInMS(String path) { return 3000; } @override void seekMusicToPosInTime(int id, int pts) { position = pts; } }