Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/KNOWN_ISSUES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Known Issues
- `VIDSOL-32`: When using an iPhone camera as your video input device, disconnecting your iPhone camera may cause your video to freeze and the video input may not automatically switch.
- `VIDSOL-28`: The publisher does not display a muted icon in the participant list when their audio is muted.
- `VIDSOL-5`: Subscriber videos may be disabled without warning.
- `VIDSOL-19`: The maximum number of displayed users is 10, even when the screen can accommodate more.
- `VIDSOL-127`: New video input devices added to the user's machine do not prompt the user to switch devices.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SubscriberWrapper } from '../../../types/session';
import getParticipantColor from '../../../utils/getParticipantColor';
import useRoomShareUrl from '../../../hooks/useRoomShareUrl';
import RightPanelTitle from '../RightPanel/RightPanelTitle';
import usePublisherContext from '../../../hooks/usePublisherContext';

const compareNameAlphabetically = (a: SubscriberWrapper, b: SubscriberWrapper) => {
const nameA = a.subscriber?.stream?.name;
Expand Down Expand Up @@ -49,6 +50,8 @@ const ParticipantList = ({ handleClose, isOpen }: ParticipantListProps): ReactEl
},
} = useUserContext();
const roomShareUrl = useRoomShareUrl();
const { isAudioEnabled } = usePublisherContext();

const copyUrl = () => {
navigator.clipboard.writeText(roomShareUrl);

Expand Down Expand Up @@ -90,7 +93,8 @@ const ParticipantList = ({ handleClose, isOpen }: ParticipantListProps): ReactEl
<ParticipantListItem
key="you"
dataTestId="participant-list-item-you"
audioLevel={publisherAudio}
hasAudio={isAudioEnabled}
audioLevel={isAudioEnabled ? publisherAudio : undefined}
name={`${name} (You)`}
initials={getInitials(name)}
avatarColor={getParticipantColor(name)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { describe, expect, it } from 'vitest';
import { describe, expect, it, beforeEach, vi, Mock } from 'vitest';
import { render, screen } from '@testing-library/react';
import { Stream } from '@vonage/client-sdk-video';
import ParticipantListItem, { ParticipantListItemProps } from './ParticipantListItem';
import useAudioLevels from '../../../hooks/useAudioLevels';
import usePublisherContext from '../../../hooks/usePublisherContext';
import { PublisherContextType } from '../../../Context/PublisherProvider';

vi.mock('../../../hooks/useAudioLevels');
vi.mock('../../../hooks/usePublisherContext');

const mockUseAudioLevels = useAudioLevels as Mock<[], number | undefined>;
const mockUsePublisherContext = usePublisherContext as Mock<[], PublisherContextType>;

describe('ParticipantListItem', () => {
const mockStream: Stream = {
Expand Down Expand Up @@ -72,4 +81,47 @@ describe('ParticipantListItem', () => {
fontSize: '14px',
});
});

describe('Publisher audio state handling', () => {
let publisherContext: PublisherContextType;
beforeEach(() => {
publisherContext = {
isAudioEnabled: true,
} as unknown as PublisherContextType;
mockUsePublisherContext.mockImplementation(() => publisherContext);
mockUseAudioLevels.mockReturnValue(50);
});

it('shows active audio state for publisher when microphone is enabled', () => {
mockUsePublisherContext.mockImplementation(() => ({
...publisherContext,
isAudioEnabled: true,
}));
mockUseAudioLevels.mockReturnValue(75);

render(<ParticipantListItem {...defaultProps} audioLevel={undefined} hasAudio />);

const participantItem = screen.getByTestId('participant-list-item');
expect(participantItem).toBeInTheDocument();

const audioIndicator = screen.getByTestId('audio-indicator');
expect(audioIndicator).toBeInTheDocument();

const micIcon = screen.getByTestId('MicIcon');
expect(micIcon).toBeInTheDocument();
});

it('shows muted state when hasAudio is false', () => {
render(<ParticipantListItem {...defaultProps} audioLevel={undefined} hasAudio={false} />);

const participantItem = screen.getByTestId('participant-list-item');
expect(participantItem).toBeInTheDocument();

const audioIndicator = screen.getByTestId('audio-indicator');
expect(audioIndicator).toBeInTheDocument();

const micOffIcon = screen.getByTestId('MicOffIcon');
expect(micOffIcon).toBeInTheDocument();
});
});
});