| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
- import { RtcManagerAdapter } from '../src/managers/rtc-manager-adapter'
- import { SttError } from '../src/core/stt-error'
- // 模拟 AgoraRTC SDK
- vi.mock('agora-rtc-sdk-ng', () => ({
- default: {
- createClient: vi.fn(() => ({
- join: vi.fn(),
- leave: vi.fn(),
- publish: vi.fn(),
- subscribe: vi.fn(),
- unsubscribe: vi.fn(),
- on: vi.fn(),
- })),
- createMicrophoneAndCameraTracks: vi.fn(() =>
- Promise.resolve([{ close: vi.fn(), isPlaying: false, play: vi.fn() }, { close: vi.fn() }])
- ),
- },
- }))
- // 模拟 token 工具
- vi.mock('../src/utils/token-utils', () => ({
- generateAgoraToken: vi.fn(() => Promise.resolve('mock-token')),
- }))
- describe('RtcManagerAdapter', () => {
- let manager: RtcManagerAdapter
- beforeEach(() => {
- manager = new RtcManagerAdapter('test-app-id', 'test-certificate')
- })
- afterEach(async () => {
- await manager.destroy()
- })
- describe('constructor', () => {
- it('should create instance with appId and certificate', () => {
- expect(manager).toBeInstanceOf(RtcManagerAdapter)
- expect(manager.isJoined).toBe(false)
- expect(manager.config).toBeUndefined()
- })
- it('should create instance without parameters', () => {
- const managerWithoutParams = new RtcManagerAdapter()
- expect(managerWithoutParams).toBeInstanceOf(RtcManagerAdapter)
- })
- })
- describe('join', () => {
- it('should join channel successfully', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- expect(manager.isJoined).toBe(true)
- expect(manager.config).toEqual(config)
- expect(manager.userId).toBe('test-user')
- expect(manager.channel).toBe('test-channel')
- })
- it('should throw error when missing required parameters', async () => {
- await expect(manager.join({} as any)).rejects.toThrow(SttError)
- await expect(manager.join({ channel: 'test' } as any)).rejects.toThrow(SttError)
- await expect(manager.join({ userId: 'test' } as any)).rejects.toThrow(SttError)
- })
- it('should throw error when already joined', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- await expect(manager.join(config)).rejects.toThrow(SttError)
- })
- it('should throw error when missing appId', async () => {
- const managerWithoutAppId = new RtcManagerAdapter()
- const config = { channel: 'test-channel', userId: 'test-user' }
- await expect(managerWithoutAppId.join(config)).rejects.toThrow(SttError)
- })
- it('should throw error when missing certificate', async () => {
- const managerWithoutCert = new RtcManagerAdapter('test-app-id')
- const config = { channel: 'test-channel', userId: 'test-user' }
- await expect(managerWithoutCert.join(config)).rejects.toThrow(SttError)
- })
- it('should emit connecting and connected events', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- const connectingSpy = vi.fn()
- const connectedSpy = vi.fn()
- manager.on('connecting', connectingSpy)
- manager.on('connected', connectedSpy)
- await manager.join(config)
- expect(connectingSpy).toHaveBeenCalledWith({
- channel: 'test-channel',
- userId: 'test-user',
- })
- expect(connectedSpy).toHaveBeenCalledWith({
- channel: 'test-channel',
- userId: 'test-user',
- })
- })
- })
- describe('createTracks', () => {
- it('should create tracks successfully', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- // 先设置事件监听器
- const localUserChangedSpy = vi.fn()
- manager.on('localUserChanged', localUserChangedSpy)
- await manager.createTracks()
- // 验证事件被触发
- expect(localUserChangedSpy).toHaveBeenCalled()
- })
- it('should throw error when not joined', async () => {
- await expect(manager.createTracks()).rejects.toThrow(SttError)
- })
- })
- describe('publish', () => {
- it('should publish tracks successfully', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- await manager.createTracks()
- await expect(manager.publish()).resolves.not.toThrow()
- })
- it('should throw error when not joined', async () => {
- await expect(manager.publish()).rejects.toThrow(SttError)
- })
- it('should throw error when tracks not created', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- await expect(manager.publish()).rejects.toThrow(SttError)
- })
- })
- describe('destroy', () => {
- it('should destroy manager successfully', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- await manager.destroy()
- expect(manager.isJoined).toBe(false)
- expect(manager.config).toBeUndefined()
- expect(manager.userId).toBe('')
- expect(manager.channel).toBe('')
- })
- it('should emit destroying and destroyed events', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- const destroyingSpy = vi.fn()
- const destroyedSpy = vi.fn()
- manager.on('destroying', destroyingSpy)
- manager.on('destroyed', destroyedSpy)
- await manager.destroy()
- expect(destroyingSpy).toHaveBeenCalled()
- expect(destroyedSpy).toHaveBeenCalled()
- })
- it('should handle destroy when not joined', async () => {
- await expect(manager.destroy()).resolves.not.toThrow()
- })
- })
- describe('event handling', () => {
- it('should handle network quality events', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- const networkQualitySpy = vi.fn()
- manager.on('networkQuality', networkQualitySpy)
- // 模拟网络质量事件
- const mockClient = await import('agora-rtc-sdk-ng')
- const client = mockClient.default.createClient()
- const networkQualityHandler = client.on.mock.calls.find(
- (call: any) => call[0] === 'network-quality'
- )?.[1]
- if (networkQualityHandler) {
- networkQualityHandler({ uplink: 5, downlink: 5 })
- expect(networkQualitySpy).toHaveBeenCalledWith({ uplink: 5, downlink: 5 })
- }
- })
- it('should handle user published events', async () => {
- const config = { channel: 'test-channel', userId: 'test-user' }
- await manager.join(config)
- const remoteUserChangedSpy = vi.fn()
- manager.on('remoteUserChanged', remoteUserChangedSpy)
- // 模拟用户发布事件
- const mockClient = await import('agora-rtc-sdk-ng')
- const client = mockClient.default.createClient()
- const userPublishedHandler = client.on.mock.calls.find(
- (call: any) => call[0] === 'user-published'
- )?.[1]
- if (userPublishedHandler) {
- const mockUser = { uid: 'remote-user', audioTrack: {}, videoTrack: {} }
- await userPublishedHandler(mockUser, 'audio')
- expect(remoteUserChangedSpy).toHaveBeenCalledWith({
- userId: 'remote-user',
- audioTrack: {},
- videoTrack: {},
- })
- }
- })
- })
- })
|