Skip to content
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
1b8aacc
rough POC
mgamis-msft Jan 11, 2022
7a7b16f
added mock video element
mgamis-msft Jan 13, 2022
6e89486
Move HTMLElement generation for videostream in MockCallAdapter
mgamis-msft Jan 14, 2022
0416b26
added state into qArgs as an option
mgamis-msft Jan 17, 2022
2468aea
Added one more video participant
mgamis-msft Jan 17, 2022
442d31d
created CallingState type
mgamis-msft Jan 20, 2022
64bc31f
HorizontalGallery paged tests added
mgamis-msft Jan 20, 2022
1478d82
Added identifiers to HorizontalGallery buttons. Clicking buttons in U…
mgamis-msft Jan 20, 2022
c6ace27
Merge branch 'main' into mgamis/mock-calling-state
mgamis-msft Jan 20, 2022
ce69a63
rename to TestCallingState, clean up and added documentation
mgamis-msft Jan 21, 2022
1286ae9
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 21, 2022
1211a61
change files
mgamis-msft Jan 21, 2022
a1a5167
address insecure randomness flag from CodeQL
mgamis-msft Jan 22, 2022
ca24e38
fixed error in call test uitls.ts
mgamis-msft Jan 24, 2022
9859c33
Change file changed from prerelease to minor
mgamis-msft Jan 24, 2022
69bf503
stable-review api changes
mgamis-msft Jan 24, 2022
4c7ed73
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 24, 2022
cd4e7b5
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 25, 2022
aa71c7b
clean up MockCallAdapter
mgamis-msft Jan 25, 2022
dac0175
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 25, 2022
4799998
removed delay in HorizontalGallery UI tests. Changed remoteParticipan…
mgamis-msft Jan 26, 2022
76e0f16
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 26, 2022
d9bbf63
small refactor
mgamis-msft Jan 26, 2022
9582202
more readable code
mgamis-msft Jan 26, 2022
96b57e0
fixed MockCallAdapter constuctor
mgamis-msft Jan 26, 2022
a6fe754
MockAdapter refactor checkpoint
mgamis-msft Jan 26, 2022
f3ab0b7
refactor checkpoint 2
mgamis-msft Jan 26, 2022
c08adf0
refactor checkpoint 3
mgamis-msft Jan 26, 2022
d6a1c21
small fixes in MockCallAdapter
mgamis-msft Jan 27, 2022
20f1d19
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 27, 2022
b2759db
Delete locally generated snapshot
mgamis-msft Jan 27, 2022
013b0e0
added clickOffPage util function
mgamis-msft Jan 27, 2022
0b30de1
Update doc
mgamis-msft Jan 27, 2022
1c437ff
small cleanup
mgamis-msft Jan 27, 2022
a6f0fe5
removed default test remote participants
mgamis-msft Jan 27, 2022
c9c4310
removed useMockAdapter query argument
mgamis-msft Jan 28, 2022
771c198
deleted old snapshots after rename
mgamis-msft Jan 28, 2022
76f58dd
Added helper function to create CallAdapter using createAzureCommunic…
mgamis-msft Jan 28, 2022
0ec2f58
buildUrlWithMockAdapter doc improvement
mgamis-msft Jan 28, 2022
8e89fdc
added wait for VideoGallery render in each test
mgamis-msft Jan 28, 2022
44fd3f7
rename snapshots
mgamis-msft Jan 28, 2022
1f66e33
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 28, 2022
632a5fc
better documentation of MockCallAdapter
mgamis-msft Jan 28, 2022
ea52be5
cleaned up MockCallingAdapter handlers
mgamis-msft Jan 28, 2022
e32b2dd
fixed initial state in MockCallAdapter constructor
mgamis-msft Jan 31, 2022
279893e
small fix
mgamis-msft Jan 31, 2022
9087cc4
clickOffPage -> clickOutsideOfPage
mgamis-msft Jan 31, 2022
308c61d
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Jan 31, 2022
295fdba
Removed snapshot updates from localization UI tests
mgamis-msft Jan 31, 2022
6f20640
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Feb 1, 2022
b1fdfc9
remove casting of param to TestCallingState
mgamis-msft Feb 1, 2022
1e6a9bd
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Feb 1, 2022
46b58ed
Merge branch 'main' into mgamis/horizontal-gallery-ui-tests
mgamis-msft Feb 2, 2022
c0a7f66
try-catch statement to parse mockCallState
mgamis-msft Feb 2, 2022
ec50d17
Update composite automation snapshots
github-actions[bot] Feb 2, 2022
a99b486
Update composite automation snapshots
github-actions[bot] Feb 2, 2022
39e9a99
Revert "try-catch statement to parse mockCallState"
mgamis-msft Feb 2, 2022
62c7a68
Revert "Revert "try-catch statement to parse mockCallState""
mgamis-msft Feb 2, 2022
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Identifiers added for HorizontalGallery left and right navigation buttons.",
"packageName": "@internal/react-components",
"email": "miguelgamis@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,8 @@ export interface _IdentifierProviderProps {

// @internal
export interface _Identifiers {
horizontalGalleryLeftNavButton: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might have been a mistake exposing _Identifiers through the public API (we thought @internal was OK for this, but unsure).

Let's not add to this anymore. Just directly use data-ui-id in the component and directly use the data-ui-id from e2e tests, like we already do for composites.

Thanks for trying to stick to this pattern...

horizontalGalleryRightNavButton: string;
messageContent: string;
messageTimestamp: string;
participantButtonPeopleMenuItem: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,8 @@ export interface _IdentifierProviderProps {

// @internal
export interface _Identifiers {
horizontalGalleryLeftNavButton: string;
horizontalGalleryRightNavButton: string;
messageContent: string;
messageTimestamp: string;
participantButtonPeopleMenuItem: string;
Expand Down
2 changes: 2 additions & 0 deletions packages/react-components/review/react-components.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ export interface _IdentifierProviderProps {

// @internal
export interface _Identifiers {
horizontalGalleryLeftNavButton: string;
horizontalGalleryRightNavButton: string;
messageContent: string;
messageTimestamp: string;
participantButtonPeopleMenuItem: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { useMemo, useState } from 'react';
import { useTheme } from '../theming';
import { BaseCustomStyles } from '../types';
import { rootStyle, childrenContainerStyle, leftRightButtonStyles } from './styles/HorizontalGallery.styles';
import { useIdentifiers } from '../identifiers';

/**
* {@link HorizontalGallery} default children per page
Expand Down Expand Up @@ -49,6 +50,8 @@ export interface HorizontalGalleryProps {
export const HorizontalGallery = (props: HorizontalGalleryProps): JSX.Element => {
const { children, childrenPerPage = DEFAULT_CHILDREN_PER_PAGE, styles } = props;

const ids = useIdentifiers();

const [page, setPage] = useState(0);

const numberOfChildren = React.Children.count(children);
Expand Down Expand Up @@ -80,6 +83,7 @@ export const HorizontalGallery = (props: HorizontalGalleryProps): JSX.Element =>
styles={styles?.previousButton}
onClick={() => setPage(Math.max(0, Math.min(lastPage, page - 1)))}
disabled={disablePreviousButton}
identifier={ids.horizontalGalleryLeftNavButton}
/>
)}
<Stack horizontal className={mergeStyles(childrenContainerStyle, { '> *': props.styles?.children })}>
Expand All @@ -92,6 +96,7 @@ export const HorizontalGallery = (props: HorizontalGalleryProps): JSX.Element =>
styles={styles?.nextButton}
onClick={() => setPage(Math.min(lastPage, page + 1))}
disabled={disableNextButton}
identifier={ids.horizontalGalleryRightNavButton}
/>
)}
</Stack>
Expand All @@ -103,13 +108,15 @@ const HorizontalGalleryNavigationButton = (props: {
styles: IStyle;
onClick?: () => void;
disabled?: boolean;
identifier?: string;
}): JSX.Element => {
const theme = useTheme();
return (
<DefaultButton
className={mergeStyles(leftRightButtonStyles(theme), props.styles)}
onClick={props.onClick}
disabled={props.disabled}
data-ui-id={props.identifier}
>
{props.icon}
</DefaultButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export interface _Identifiers {
videoGallery: string;
/** `data-ui-id` value for `VideoTile` Component */
videoTile: string;
/** `data-ui-id` value for `HorizontalGallery` Component's left navigation button */
horizontalGalleryLeftNavButton: string;
/** `data-ui-id` value for `HorizontalGallery` Component's right navigation button */
horizontalGalleryRightNavButton: string;
}

const defaultIdentifiers: _Identifiers = {
Expand All @@ -52,7 +56,9 @@ const defaultIdentifiers: _Identifiers = {
messageTimestamp: 'message-timestamp',
typingIndicator: 'typing-indicator',
videoGallery: 'video-gallery',
videoTile: 'video-tile'
videoTile: 'video-tile',
horizontalGalleryLeftNavButton: 'horizontal-gallery-left-nav-button',
horizontalGalleryRightNavButton: 'horizontal-gallery-right-nav-button'
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,8 @@ export interface _IdentifierProviderProps {

// @internal
export interface _Identifiers {
horizontalGalleryLeftNavButton: string;
horizontalGalleryRightNavButton: string;
messageContent: string;
messageTimestamp: string;
participantButtonPeopleMenuItem: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { test } from './fixture';
import { expect } from '@playwright/test';
import { buildUrlWithMockAdapter } from './utils';
import { dataUiId, pageClick, clickOutsideOfPage, waitForPageFontsLoaded, waitForSelector } from '../common/utils';
import { IDS } from '../common/constants';

test.describe('HorizontalGallery tests', async () => {
test('HorizontalGallery should have 1 audio participant', async ({ pages, serverUrl }) => {
const page = pages[0];
const testRemoteParticipants = [
{
displayName: 'Paul Bridges',
isSpeaking: true,
isVideoStreamAvailable: true
},
{
displayName: 'Eryka Klein'
},
{
displayName: 'Fiona Harper',
isVideoStreamAvailable: true
}
];
await page.goto(
buildUrlWithMockAdapter(serverUrl, {
remoteParticipants: testRemoteParticipants
})
);
// Click off page to turn away initial aria label
await clickOutsideOfPage(page);
await waitForSelector(page, dataUiId(IDS.videoGallery));
await waitForPageFontsLoaded(page);
Comment thread
JamesBurnside marked this conversation as resolved.
expect(await page.screenshot()).toMatchSnapshot('horizontal-gallery-with-1-audio-participant.png');
});

test('HorizontalGallery should have multiple audio participants spanning multiple pages. Navigation buttons should work.', async ({
pages,
serverUrl
}) => {
const page = pages[0];
const testRemoteParticipants = [
{
displayName: 'Paul Bridges',
isSpeaking: true,
isVideoStreamAvailable: true
},
{
displayName: 'Eryka Klein'
},
{
displayName: 'Fiona Harper',
isVideoStreamAvailable: true
},
{
displayName: 'Pardeep Singh'
},
{
displayName: 'Reina Takizawa',
isSpeaking: true
},
{
displayName: 'Vasily Podkolzin',
isMuted: true
},
{
displayName: 'Luciana Rodriguez'
},
{
displayName: 'Antonie van Leeuwenhoek'
},
{
displayName: 'Gerald Ho'
}
];
await page.goto(
buildUrlWithMockAdapter(serverUrl, {
remoteParticipants: testRemoteParticipants
})
);
// Click off page to turn away initial aria label
await clickOutsideOfPage(page);
await waitForSelector(page, dataUiId(IDS.videoGallery));
await waitForPageFontsLoaded(page);
Comment thread
JamesBurnside marked this conversation as resolved.
expect(await page.screenshot()).toMatchSnapshot('horizontal-gallery-with-many-audio-participants-on-page-1.png');
await waitForSelector(page, dataUiId(IDS.horizontalGalleryRightNavButton));
await pageClick(page, dataUiId(IDS.horizontalGalleryRightNavButton));
expect(await page.screenshot()).toMatchSnapshot('horizontal-gallery-with-many-audio-participants-on-page-2.png');
await waitForSelector(page, dataUiId(IDS.horizontalGalleryLeftNavButton));
await pageClick(page, dataUiId(IDS.horizontalGalleryLeftNavButton));
expect(await page.screenshot()).toMatchSnapshot('horizontal-gallery-with-many-audio-participants-on-page-1.png');
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

/**
* Calling state passed as as a query argument to set up MockCallingAdapter in playwright test
*/
export type TestCallingState = {
remoteParticipants?: TestRemoteParticipant[];
};

/**
* Remote participant state used in {@link TestCallingState}
*/
export type TestRemoteParticipant = {
displayName: string;
isMuted?: boolean;
isSpeaking?: boolean;
isVideoStreamAvailable?: boolean;
};
40 changes: 25 additions & 15 deletions packages/react-composites/tests/browser/call/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,15 @@ import {
import { IDS } from '../../common/constants';
import { isMobile, verifyParamExists } from '../../common/testAppUtils';
import memoizeOne from 'memoize-one';
import { FontIcon, Icon, IContextualMenuItem, mergeStyles } from '@fluentui/react';
import { Icon, IContextualMenuItem, mergeStyles } from '@fluentui/react';
import { fromFlatCommunicationIdentifier } from '@internal/acs-ui-common';
import { MockCallAdapter } from './mocks/MockCallAdapter';
import { TestCallingState } from '../TestCallingState';

const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());

// Required params
const displayName = verifyParamExists(params.displayName, 'displayName');
const token = verifyParamExists(params.token, 'token');
const groupId = verifyParamExists(params.groupId, 'groupId');
const userId = verifyParamExists(params.userId, 'userId');

// Optional params
const mockCallState = JSON.parse(params.mockCallState) as TestCallingState;
const useFrLocale = Boolean(params.useFrLocale);
const showCallDescription = Boolean(params.showCallDescription);
const injectParticipantMenuItems = Boolean(params.injectParticipantMenuItems);
Expand All @@ -43,13 +39,11 @@ function App(): JSX.Element {

useEffect(() => {
const initialize = async (): Promise<void> => {
const newAdapter = await createAzureCommunicationCallAdapter({
userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier,
displayName,
credential: new AzureCommunicationTokenCredential(token),
locator: { groupId: groupId }
});
setCallAdapter(wrapAdapterForTests(newAdapter));
if (mockCallState) {
setCallAdapter(wrapAdapterForTests(new MockCallAdapter(mockCallState)));
} else {
setCallAdapter(wrapAdapterForTests(await createCallAdapterWithCredentials()));
}
};

initialize();
Expand Down Expand Up @@ -154,6 +148,22 @@ const unsetSpeakingWhileMicrophoneIsMuted = (state: CallAdapterState): CallAdapt
*/
const memoizedUnsetSpeakingWhileMicrophoneIsMuted = memoizeOne(unsetSpeakingWhileMicrophoneIsMuted);

// Function to create call adapter using createAzureCommunicationCallAdapter
const createCallAdapterWithCredentials = async (): Promise<CallAdapter> => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice tidy refactor!

const displayName = verifyParamExists(params.displayName, 'displayName');
const token = verifyParamExists(params.token, 'token');
const groupId = verifyParamExists(params.groupId, 'groupId');
const userId = verifyParamExists(params.userId, 'userId');

const callAdapter = await createAzureCommunicationCallAdapter({
userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier,
displayName,
credential: new AzureCommunicationTokenCredential(token),
locator: { groupId: groupId }
});
return callAdapter;
};

function onFetchParticipantMenuItems(): IContextualMenuItem[] {
return [
{
Expand Down
Loading