feat: Add incoming call modal
This commit is contained in:
@@ -66,11 +66,59 @@ describe('DirectCallService', () => {
|
||||
|
||||
await vi.waitFor(() => expect(context.service.visibleActiveSessions()).toHaveLength(1));
|
||||
await vi.waitFor(() => expect(context.audio.playLoop).toHaveBeenCalledWith(AppSound.Call));
|
||||
expect(context.service.incomingCall()?.callId).toBe('dm-alice-bob');
|
||||
|
||||
context.directCallEvents.next(createCallEvent('leave', alice, ['alice', 'bob']));
|
||||
|
||||
await vi.waitFor(() => expect(context.service.visibleActiveSessions()).toHaveLength(0));
|
||||
expect(context.audio.stop).toHaveBeenCalledWith(AppSound.Call);
|
||||
expect(context.service.incomingCall()).toBeNull();
|
||||
});
|
||||
|
||||
it('suppresses incoming call audio and modal state while do not disturb is active', async () => {
|
||||
const busyBob = { ...bob, status: 'busy' as const };
|
||||
const context = createServiceContext({ currentUser: busyBob, allUsers: [alice, busyBob] });
|
||||
|
||||
context.directCallEvents.next(createCallEvent('ring', alice, ['alice', 'bob']));
|
||||
|
||||
await vi.waitFor(() => expect(context.service.sessionById('dm-alice-bob')).not.toBeNull());
|
||||
expect(context.audio.playLoop).not.toHaveBeenCalled();
|
||||
await vi.waitFor(() => expect(context.audio.stop).toHaveBeenCalledWith(AppSound.Call));
|
||||
expect(context.service.incomingCall()).toBeNull();
|
||||
});
|
||||
|
||||
it('answers an incoming call from the modal action', async () => {
|
||||
const context = createServiceContext({ currentUser: bob, allUsers: [alice, bob] });
|
||||
|
||||
context.directCallEvents.next(createCallEvent('ring', alice, ['alice', 'bob']));
|
||||
|
||||
await vi.waitFor(() => expect(context.service.incomingCall()?.callId).toBe('dm-alice-bob'));
|
||||
await context.service.answerIncomingCall('dm-alice-bob');
|
||||
|
||||
expect(context.audio.stop).toHaveBeenCalledWith(AppSound.Call);
|
||||
expect(context.router.navigate).toHaveBeenCalledWith(['/call', 'dm-alice-bob']);
|
||||
expect(context.service.incomingCall()).toBeNull();
|
||||
});
|
||||
|
||||
it('declines an incoming call from the modal action', async () => {
|
||||
const context = createServiceContext({ currentUser: bob, allUsers: [alice, bob] });
|
||||
|
||||
context.directCallEvents.next(createCallEvent('ring', alice, ['alice', 'bob']));
|
||||
|
||||
await vi.waitFor(() => expect(context.service.incomingCall()?.callId).toBe('dm-alice-bob'));
|
||||
context.service.declineIncomingCall('dm-alice-bob');
|
||||
|
||||
expect(context.audio.stop).toHaveBeenCalledWith(AppSound.Call);
|
||||
expect(context.delivery.sendCallEvent).toHaveBeenCalledWith('alice', expect.objectContaining({
|
||||
directCall: expect.objectContaining({
|
||||
action: 'leave',
|
||||
callId: 'dm-alice-bob'
|
||||
}),
|
||||
type: 'direct-call'
|
||||
}));
|
||||
|
||||
expect(context.service.sessionById('dm-alice-bob')?.status).toBe('ended');
|
||||
expect(context.service.incomingCall()).toBeNull();
|
||||
});
|
||||
|
||||
it('rejoins an existing direct call instead of ringing a duplicate after leaving locally', async () => {
|
||||
@@ -91,9 +139,21 @@ describe('DirectCallService', () => {
|
||||
});
|
||||
|
||||
it('reuses an existing group call by conversation id instead of creating a duplicate call', async () => {
|
||||
const context = createServiceContext({ currentUser: alice, allUsers: [alice, bob, charlie] });
|
||||
const session = createGroupSession('dm-original-call', 'dm-group-live', [alice, bob, charlie]);
|
||||
const conversation = createGroupConversation('dm-group-live', [alice, bob, charlie]);
|
||||
const context = createServiceContext({ currentUser: alice, allUsers: [
|
||||
alice,
|
||||
bob,
|
||||
charlie
|
||||
] });
|
||||
const session = createGroupSession('dm-original-call', 'dm-group-live', [
|
||||
alice,
|
||||
bob,
|
||||
charlie
|
||||
]);
|
||||
const conversation = createGroupConversation('dm-group-live', [
|
||||
alice,
|
||||
bob,
|
||||
charlie
|
||||
]);
|
||||
|
||||
session.participants.alice.joined = false;
|
||||
session.participants.bob.joined = true;
|
||||
@@ -110,7 +170,11 @@ describe('DirectCallService', () => {
|
||||
});
|
||||
|
||||
it('leaves a joined call before joining a different call', async () => {
|
||||
const context = createServiceContext({ currentUser: alice, allUsers: [alice, bob, charlie] });
|
||||
const context = createServiceContext({ currentUser: alice, allUsers: [
|
||||
alice,
|
||||
bob,
|
||||
charlie
|
||||
] });
|
||||
const firstSession = createSession('connected', true);
|
||||
const nextSession = createDirectSession('dm-alice-charlie', alice, charlie, 'connected', false);
|
||||
|
||||
@@ -158,6 +222,7 @@ describe('DirectCallService', () => {
|
||||
serverId: 'server-1'
|
||||
})
|
||||
}));
|
||||
|
||||
expect(context.voiceSession.endSession).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user