VideoGallery Calling Participant tests (#2176)
* VideoTile call state * Change files * Update comment * add beta tag to videotilecallstate prop * Update api.md * Updating api.md * Tweak prop name * Update changelog * Tweak prop name * updating api.md * Tweaking types * update changelog * Update api.md * Return participant state from videoGallerySelector and wire it in gallery * Change files * Tweak changelog * Fixing build * Tweaking state conversion logic in videoGallerySelector * Localization for video tile participant state prop * Conditionally remove pstn code from participant item * Update api.md * Update Api.md * resolving PR comments * Change files * Debugging video tile participant state display logic * update api.md * Resolving PR comments * fixing conditional compilation * fixing conditional compilation * fixing conditional compilation * Fixing conditional compilation errors * Change files * Updating types to match video tile participant state * updating api.md * update video gallery logic * debugging * Change files * Remove duplicate interface * update Media Gallery * update vigeogallery tile creation * update mediagallery on render * update media gallery styles * Update locale strings to match figma * build api files * add tests for gridview and horizontal view * add tests for 1 video part and joining * remove test.only * update tests * add screensharing tests and fix typing issue * update api * fix Ringing error * update tests * fix deps array * add third case for ringing * fix ringing state * update names of tests * add new helper functions * remove test only * update participant item state name * update API docs * update initial state of PSTN and 1:n * Update composite automation snapshots * Change files * Update composite automation snapshots * Update composite automation snapshots * Update composite automation snapshots * Update composite automation snapshots Co-authored-by: Anjul Garg <anjulgarg@live.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
@ -169,4 +169,4 @@ jobs:
|
|||
curl -X POST -H 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' https://api.github.com/repos/Azure/communication-ui-library/issues -d '{"title":"Nightly workflow to release alpha package failed", "body": "Please investigate failures of https://github.com/Azure/communication-ui-library/actions/workflows/nightly-cd.yml", "labels":["NIGHTLY_CD_FAILURE"]}'
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "Add tests for PSTN and 1:N calling in the videoGallery and horizontalGallery",
|
||||
"packageName": "@internal/react-components",
|
||||
"email": "94866715+dmceachernmsft@users.noreply.github.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -1210,7 +1210,7 @@ export const _RemoteVideoTile: React_2.MemoExoticComponent<(props: {
|
|||
showMuteIndicator?: boolean | undefined;
|
||||
showLabel?: boolean | undefined;
|
||||
personaMinSize?: number | undefined;
|
||||
state?: ParticipantState | undefined;
|
||||
participantState?: ParticipantState | undefined;
|
||||
}) => JSX.Element>;
|
||||
|
||||
// @beta (undocumented)
|
||||
|
|
|
@ -1134,7 +1134,7 @@ export const _RemoteVideoTile: React_2.MemoExoticComponent<(props: {
|
|||
showMuteIndicator?: boolean | undefined;
|
||||
showLabel?: boolean | undefined;
|
||||
personaMinSize?: number | undefined;
|
||||
state?: ParticipantState | undefined;
|
||||
participantState?: ParticipantState | undefined;
|
||||
}) => JSX.Element>;
|
||||
|
||||
// @public
|
||||
|
|
|
@ -148,6 +148,7 @@ export const ParticipantItem = (props: ParticipantItemProps): JSX.Element => {
|
|||
me,
|
||||
onClick,
|
||||
showParticipantOverflowTooltip
|
||||
/* @conditional-compile-remove(PSTN-calls) */
|
||||
} = props;
|
||||
const [itemHovered, setItemHovered] = useState<boolean>(false);
|
||||
const [menuHidden, setMenuHidden] = useState<boolean>(true);
|
||||
|
|
|
@ -37,7 +37,7 @@ export const _RemoteVideoTile = React.memo(
|
|||
showMuteIndicator?: boolean;
|
||||
showLabel?: boolean;
|
||||
personaMinSize?: number;
|
||||
state?: ParticipantState;
|
||||
participantState?: ParticipantState;
|
||||
}) => {
|
||||
const {
|
||||
isAvailable,
|
||||
|
@ -55,7 +55,7 @@ export const _RemoteVideoTile = React.memo(
|
|||
showMuteIndicator,
|
||||
/* @conditional-compile-remove(one-to-n-calling) */
|
||||
/* @conditional-compile-remove(PSTN-calls) */
|
||||
state
|
||||
participantState
|
||||
} = props;
|
||||
|
||||
const remoteVideoStreamProps: RemoteVideoStreamLifecycleMaintainerProps = useMemo(
|
||||
|
@ -113,7 +113,7 @@ export const _RemoteVideoTile = React.memo(
|
|||
personaMinSize={props.personaMinSize}
|
||||
/* @conditional-compile-remove(one-to-n-calling) */
|
||||
/* @conditional-compile-remove(PSTN-calls) */
|
||||
participantState={state}
|
||||
participantState={participantState}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -344,7 +344,7 @@ export const VideoGallery = (props: VideoGalleryProps): JSX.Element => {
|
|||
onRenderAvatar={onRenderAvatar}
|
||||
showMuteIndicator={showMuteIndicator}
|
||||
/* @conditional-compile-remove(PSTN-calls) */
|
||||
state={participant.state}
|
||||
participantState={participant.state}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -31,7 +31,7 @@ Both hermetic and live tests use [playwright](https://playwright.dev/) test fram
|
|||
```
|
||||
* Build the test applications.
|
||||
```sh
|
||||
rush build:e2e
|
||||
rushx build:e2e
|
||||
```
|
||||
|
||||
### Live tests
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
addScreenshareStream,
|
||||
addVideoStream,
|
||||
buildUrlWithMockAdapter,
|
||||
defaultMockCallAdapterState,
|
||||
defaultMockRemoteParticipant,
|
||||
defaultMockRemotePSTNParticipant,
|
||||
test
|
||||
} from './fixture';
|
||||
import { expect } from '@playwright/test';
|
||||
import { dataUiId, pageClick, waitForSelector, stableScreenshot } from '../../common/utils';
|
||||
import { dataUiId, pageClick, waitForSelector, stableScreenshot, isTestProfileStableFlavor } from '../../common/utils';
|
||||
import { IDS } from '../../common/constants';
|
||||
|
||||
test.describe('HorizontalGallery tests', async () => {
|
||||
|
@ -73,4 +75,135 @@ test.describe('HorizontalGallery tests', async () => {
|
|||
'horizontal-gallery-with-many-audio-participants-on-page-1.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('HorizontalGallery should have 1 PSTN participant in the horizontal gallery', async ({ page, serverUrl }) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
addVideoStream(paul, true);
|
||||
const vasily = defaultMockRemoteParticipant('Vasily Podkolzin');
|
||||
vasily.state = 'Connecting';
|
||||
|
||||
const participants = [paul, vasily];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'horizontal-gallery-with-joining-participant.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('HorizontalGallery should have multiple audio participants and 1 PSTN participant', async ({
|
||||
page,
|
||||
serverUrl
|
||||
}) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
addVideoStream(paul, true);
|
||||
paul.isSpeaking = true;
|
||||
const fiona = defaultMockRemoteParticipant('Fiona Harper');
|
||||
const reina = defaultMockRemoteParticipant('Reina Takizawa');
|
||||
reina.isSpeaking = true;
|
||||
const phoneUser = defaultMockRemotePSTNParticipant('+15555555555');
|
||||
phoneUser.state = 'Connecting';
|
||||
|
||||
const participants = [paul, fiona, reina, phoneUser];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'horizontal-gallery-with-joining-participant-with-audio-participants.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('HorizontalGallery should have multiple audio participants and 1 PSTN participant on second page', async ({
|
||||
page,
|
||||
serverUrl
|
||||
}) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
addVideoStream(paul, true);
|
||||
paul.isSpeaking = true;
|
||||
const fiona = defaultMockRemoteParticipant('Fiona Harper');
|
||||
addVideoStream(fiona, true);
|
||||
const reina = defaultMockRemoteParticipant('Reina Takizawa');
|
||||
reina.isSpeaking = true;
|
||||
const phoneUser = defaultMockRemotePSTNParticipant('+15555555555');
|
||||
phoneUser.state = 'Connecting';
|
||||
|
||||
const participants = [
|
||||
paul,
|
||||
fiona,
|
||||
reina,
|
||||
phoneUser,
|
||||
defaultMockRemoteParticipant('Luciana Rodriguez'),
|
||||
defaultMockRemoteParticipant('Antonie van Leeuwenhoek'),
|
||||
defaultMockRemoteParticipant('Gerald Ho'),
|
||||
defaultMockRemoteParticipant('Pardeep Singh'),
|
||||
defaultMockRemoteParticipant('Eryka Klein')
|
||||
];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
await waitForSelector(page, dataUiId(IDS.horizontalGalleryRightNavButton));
|
||||
await pageClick(page, dataUiId(IDS.horizontalGalleryRightNavButton));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'horizontal-gallery-with-joining-participant-with-multi-page.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('HorizontalGallery should have 2 video participants during screenshare and 1 PSTN participant', async ({
|
||||
page,
|
||||
serverUrl
|
||||
}) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
addVideoStream(paul, true);
|
||||
addScreenshareStream(paul, true);
|
||||
paul.isSpeaking = true;
|
||||
const fiona = defaultMockRemoteParticipant('Fiona Harper');
|
||||
addVideoStream(fiona, true);
|
||||
const reina = defaultMockRemoteParticipant('Reina Takizawa');
|
||||
reina.isSpeaking = true;
|
||||
const phoneUser = defaultMockRemotePSTNParticipant('+15555555555');
|
||||
phoneUser.state = 'Connecting';
|
||||
|
||||
const participants = [paul, fiona, reina, phoneUser];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'horizontal-gallery-with-joining-participant-with-screen-share-and-video.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('Horizontal gallery Should have 1 PSTN and 1 1-N participants', async ({ page, serverUrl }) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const reina = defaultMockRemoteParticipant('Reina Takizawa');
|
||||
addVideoStream(reina, true);
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
paul.state = 'Ringing';
|
||||
const phoneUser = defaultMockRemotePSTNParticipant('+15555555555');
|
||||
phoneUser.state = 'Connecting';
|
||||
|
||||
const participants = [reina, paul, phoneUser];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'horizontal-gallery-with-2-joining-participants.png'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {
|
||||
buildUrlWithMockAdapter,
|
||||
defaultMockCallAdapterState,
|
||||
defaultMockRemoteParticipant,
|
||||
defaultMockRemotePSTNParticipant,
|
||||
test
|
||||
} from './fixture';
|
||||
import { expect } from '@playwright/test';
|
||||
import { dataUiId, waitForSelector, stableScreenshot, isTestProfileStableFlavor } from '../../common/utils';
|
||||
import { IDS } from '../../common/constants';
|
||||
|
||||
test.describe('VideoGallery tests', async () => {
|
||||
test('VideoGallery Should have 1 Audio participant and one PSTN participant', async ({ page, serverUrl }) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
const vasily = defaultMockRemoteParticipant('Vasily Podkolzin');
|
||||
vasily.isMuted = true;
|
||||
vasily.state = 'Connecting';
|
||||
|
||||
const participants = [paul, vasily];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'video-gallery-with-one-joining-gridview-participant.png'
|
||||
);
|
||||
});
|
||||
|
||||
test('VideoGallery Should have 1 PSTN and 1 1-N participants', async ({ page, serverUrl }) => {
|
||||
test.skip(isTestProfileStableFlavor());
|
||||
|
||||
const paul = defaultMockRemoteParticipant('Paul Bridges');
|
||||
paul.state = 'Ringing';
|
||||
const phoneUser = defaultMockRemotePSTNParticipant('+15555555555');
|
||||
phoneUser.state = 'Connecting';
|
||||
|
||||
const participants = [paul, phoneUser];
|
||||
const initialState = defaultMockCallAdapterState(participants);
|
||||
|
||||
await page.goto(buildUrlWithMockAdapter(serverUrl, initialState));
|
||||
|
||||
await waitForSelector(page, dataUiId(IDS.videoGallery));
|
||||
expect(await stableScreenshot(page, { dismissTooltips: true })).toMatchSnapshot(
|
||||
'video-gallery-with-2-joining-gridview-participant.png'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -127,6 +127,22 @@ export function defaultMockRemoteParticipant(displayName: string): MockRemotePar
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default {@link MockRemoteParticipantState} for a PSTN participant in a hermetic e2e test
|
||||
*
|
||||
* use to add PSTN participants to the {@link defaultCallAdapterState}
|
||||
*/
|
||||
export function defaultMockRemotePSTNParticipant(phoneNumber: string): MockRemoteParticipantState {
|
||||
return {
|
||||
identifier: { kind: 'phoneNumber', phoneNumber: `${phoneNumber}` },
|
||||
state: 'Connected',
|
||||
videoStreams: {},
|
||||
isMuted: true,
|
||||
isSpeaking: false,
|
||||
displayName: phoneNumber
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a video stream to {@link MockRemoteParticipantState}.
|
||||
*
|
||||
|
|
После Ширина: | Высота: | Размер: 21 KiB |
После Ширина: | Высота: | Размер: 33 KiB |
После Ширина: | Высота: | Размер: 47 KiB |
После Ширина: | Высота: | Размер: 18 KiB |
После Ширина: | Высота: | Размер: 27 KiB |
После Ширина: | Высота: | Размер: 42 KiB |
После Ширина: | Высота: | Размер: 23 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 44 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 29 KiB |
После Ширина: | Высота: | Размер: 52 KiB |
После Ширина: | Высота: | Размер: 24 KiB |
После Ширина: | Высота: | Размер: 24 KiB |
После Ширина: | Высота: | Размер: 39 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 32 KiB |
После Ширина: | Высота: | Размер: 58 KiB |
После Ширина: | Высота: | Размер: 25 KiB |
После Ширина: | Высота: | Размер: 32 KiB |
После Ширина: | Высота: | Размер: 58 KiB |
После Ширина: | Высота: | Размер: 29 KiB |
После Ширина: | Высота: | Размер: 50 KiB |
После Ширина: | Высота: | Размер: 73 KiB |