Skip to content

Commit

Permalink
feat(tests): Grid, FF and iframeAPI tests. (#15372)
Browse files Browse the repository at this point in the history
* fix(tests): Fix include/excludes of tests based on participant count.

* feat(tests): Define context globally.

The context is being created on every new suite in before hook.

* feat(tests): Drop extra char in room name.

* feat(tests): Adds an option to load iframeAPI.

* feat(tests): Adds some ts types.

* fix(tests): Fix iframeAPI helper with events received too early.

* fix(tests): Fix iframeAPI helper detecting own role changed.

* feat(tests): Adds run script to start tests with local dev server.

* feat(tests): Adds participants iframeAPI tests.

* feat(tests): Updates wdio dependencies.

* feat: Adds grid config.

* feat: Simplify iframeAPI.

Drop URL params.

* feat: Adds tenant to iframeAPI.

* feat: Adds firefox target.

Certain tests are disable as not supported on FF. Missing upload file function for iframeAPI helper. Missing option to set audio file as a mic source.

* fix: Fix using tenant from baseUrl.

* feat: Adds audio only tests.

* feat: Adds option to generate tokens for the moderator.

* feat: Adds option to test and webhooks.

* fix: Improve error stack trace on error.

* fix: Address comments.

* fix: Fix test exclusion for FF.

* squash: Revert the strophe change and add a comment.
  • Loading branch information
damencho authored Dec 10, 2024
1 parent cad3730 commit b901717
Show file tree
Hide file tree
Showing 24 changed files with 1,864 additions and 121 deletions.
336 changes: 271 additions & 65 deletions package-lock.json

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
"@types/dom-screen-wake-lock": "1.0.1",
"@types/jasmine": "5.1.4",
"@types/js-md5": "0.4.3",
"@types/jsonwebtoken": "9.0.7",
"@types/lodash-es": "4.17.12",
"@types/moment-duration-format": "2.2.6",
"@types/offscreencanvas": "2019.7.2",
Expand All @@ -161,11 +162,11 @@
"@typescript-eslint/eslint-plugin": "5.59.5",
"@typescript-eslint/parser": "5.59.5",
"@wdio/allure-reporter": "9.2.14",
"@wdio/cli": "9.2.14",
"@wdio/globals": "9.2.14",
"@wdio/jasmine-framework": "9.2.14",
"@wdio/cli": "9.4.1",
"@wdio/globals": "9.4.1",
"@wdio/jasmine-framework": "9.4.1",
"@wdio/junit-reporter": "9.2.14",
"@wdio/local-runner": "9.2.15",
"@wdio/local-runner": "9.4.1",
"babel-loader": "9.1.0",
"babel-plugin-optional-require": "0.3.1",
"circular-dependency-plugin": "5.2.0",
Expand All @@ -178,6 +179,7 @@
"eslint-plugin-react-native": "4.0.0",
"eslint-plugin-typescript-sort-keys": "2.3.0",
"jetifier": "1.6.4",
"jsonwebtoken": "9.0.2",
"metro-react-native-babel-preset": "0.77.0",
"patch-package": "6.4.7",
"process": "0.11.10",
Expand All @@ -187,7 +189,7 @@
"ts-loader": "9.4.2",
"typescript": "5.0.4",
"unorm": "1.6.0",
"webdriverio": "9.2.14",
"webdriverio": "9.4.1",
"webpack": "5.95.0",
"webpack-bundle-analyzer": "4.4.2",
"webpack-cli": "5.1.4",
Expand Down Expand Up @@ -215,7 +217,10 @@
"tsc-test:web": "tsc --project tsconfig.web.json --listFilesOnly | grep -v node_modules | grep native",
"tsc-test:native": "tsc --project tsconfig.native.json --listFilesOnly | grep -v node_modules | grep web",
"start": "make dev",
"test": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.conf.ts"
"test": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.conf.ts",
"test-ff": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.firefox.conf.ts",
"test-dev": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.dev.conf.ts",
"test-grid": "DOTENV_CONFIG_PATH=tests/.env wdio run tests/wdio.grid.conf.ts"
},
"resolutions": {
"@types/react": "17.0.14",
Expand Down
16 changes: 16 additions & 0 deletions tests/env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,19 @@

# The path to the browser video capture file
#VIDEO_CAPTURE_FILE=tests/resources/FourPeople_1280x720_30.y4m

# The path to the helper iframe page that will be used for the iframeAPI tests
#IFRAME_PAGE_BASE=

# The grid host url (https://mygrid.com/wd/hub)
#GRID_HOST_URL=

# The path to the private key used for generating JWT token (.pk)
#JWT_PRIVATE_KEY_PATH=
# The kid to use in the token
#JWT_KID=

# The address of the webhooks proxy used to test the webhooks feature (e.g. wss://your.service/?tenant=sometenant)
#WEBHOOKS_PROXY_URL=
# A shared secret to authenticate the webhook proxy connection
#WEBHOOKS_PROXY_SHARED_SECRET=
5 changes: 5 additions & 0 deletions tests/globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { IContext } from './helpers/types';

declare global {
const context: IContext;
}
137 changes: 117 additions & 20 deletions tests/helpers/Participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { multiremotebrowser } from '@wdio/globals';
import { IConfig } from '../../react/features/base/config/configType';
import { urlObjectToString } from '../../react/features/base/util/uri';
import Filmstrip from '../pageobjects/Filmstrip';
import IframeAPI from '../pageobjects/IframeAPI';
import ParticipantsPane from '../pageobjects/ParticipantsPane';
import Toolbar from '../pageobjects/Toolbar';
import VideoQualityDialog from '../pageobjects/VideoQualityDialog';

import { LOG_PREFIX, logInfo } from './browserLogger';
import { IContext } from './participants';
import { IContext } from './types';

/**
* Participant.
Expand All @@ -19,9 +22,9 @@ export class Participant {
*
* @private
*/
private context: { roomName: string; };
private _name: string;
private _endpointId: string;
private _jwt?: string;

/**
* The default config to use when joining.
Expand Down Expand Up @@ -59,17 +62,19 @@ export class Participant {
* Creates a participant with given name.
*
* @param {string} name - The name of the participant.
* @param {string }jwt - The jwt if any.
*/
constructor(name: string) {
constructor(name: string, jwt?: string) {
this._name = name;
this._jwt = jwt;
}

/**
* Returns participant endpoint ID.
*
* @returns {Promise<string>} The endpoint ID.
*/
async getEndpointId() {
async getEndpointId(): Promise<string> {
if (!this._endpointId) {
this._endpointId = await this.driver.execute(() => { // eslint-disable-line arrow-body-style
return APP.conference.getMyUserId();
Expand Down Expand Up @@ -99,7 +104,7 @@ export class Participant {
* @param {string} message - The message to log.
* @returns {void}
*/
log(message: string) {
log(message: string): void {
logInfo(this.driver, message);
}

Expand All @@ -110,10 +115,8 @@ export class Participant {
* @param {boolean} skipInMeetingChecks - Whether to skip in meeting checks.
* @returns {Promise<void>}
*/
async joinConference(context: IContext, skipInMeetingChecks = false) {
this.context = context;

const url = urlObjectToString({
async joinConference(context: IContext, skipInMeetingChecks = false): Promise<void> {
const config = {
room: context.roomName,
configOverwrite: this.config,
interfaceConfigOverwrite: {
Expand All @@ -122,14 +125,47 @@ export class Participant {
userInfo: {
displayName: this._name
}
}) || '';
};

if (context.iframeAPI) {
config.room = 'iframeAPITest.html';
}

let url = urlObjectToString(config) || '';

if (context.iframeAPI) {
const baseUrl = new URL(this.driver.options.baseUrl || '');

// @ts-ignore
url = `${this.driver.iframePageBase}${url}&domain="${baseUrl.host}"&room="${context.roomName}"`;

if (baseUrl.pathname.length > 1) {
// remove leading slash
url = `${url}&tenant="${baseUrl.pathname.substring(1)}"`;
}
}
if (this._jwt) {
url = `${url}&jwt="${this._jwt}"`;
}

await this.driver.setTimeout({ 'pageLoad': 30000 });

await this.driver.url(url);
// workaround for https://github.com/webdriverio/webdriverio/issues/13956
if (url.startsWith('file://')) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
await this.driver.url(url).catch(() => {});
} else {
await this.driver.url(url.substring(1)); // drop the leading '/' so we can use the tenant if any
}

await this.waitForPageToLoad();

if (context.iframeAPI) {
const mainFrame = this.driver.$('iframe');

await this.driver.switchFrame(mainFrame);
}

await this.waitToJoinMUC();

await this.postLoadProcess(skipInMeetingChecks);
Expand All @@ -142,7 +178,7 @@ export class Participant {
* @returns {Promise<void>}
* @private
*/
private async postLoadProcess(skipInMeetingChecks: boolean) {
private async postLoadProcess(skipInMeetingChecks: boolean): Promise<void> {
const driver = this.driver;

const parallel = [];
Expand Down Expand Up @@ -189,7 +225,7 @@ export class Participant {
*
* @returns {Promise<void>}
*/
async waitForPageToLoad() {
async waitForPageToLoad(): Promise<void> {
return this.driver.waitUntil(
() => this.driver.execute(() => document.readyState === 'complete'),
{
Expand All @@ -199,14 +235,21 @@ export class Participant {
);
}

/**
* Checks if the participant is in the meeting.
*/
isInMuc() {
return this.driver.execute(() => APP.conference.isJoined());
}

/**
* Waits to join the muc.
*
* @returns {Promise<void>}
*/
async waitToJoinMUC() {
async waitToJoinMUC(): Promise<void> {
return this.driver.waitUntil(
() => this.driver.execute(() => APP.conference.isJoined()),
() => this.isInMuc(),
{
timeout: 10_000, // 10 seconds
timeoutMsg: 'Timeout waiting to join muc.'
Expand All @@ -219,7 +262,7 @@ export class Participant {
*
* @returns {Promise<void>}
*/
async waitForIceConnected() {
async waitForIceConnected(): Promise<void> {
const driver = this.driver;

return driver.waitUntil(async () =>
Expand All @@ -234,7 +277,7 @@ export class Participant {
*
* @returns {Promise<void>}
*/
async waitForSendReceiveData() {
async waitForSendReceiveData(): Promise<void> {
const driver = this.driver;

return driver.waitUntil(async () =>
Expand All @@ -259,7 +302,7 @@ export class Participant {
* @param {number} number - The number of remote streams o wait for.
* @returns {Promise<void>}
*/
waitForRemoteStreams(number: number) {
waitForRemoteStreams(number: number): Promise<void> {
const driver = this.driver;

return driver.waitUntil(async () =>
Expand All @@ -274,7 +317,7 @@ export class Participant {
*
* @returns {Toolbar}
*/
getToolbar() {
getToolbar(): Toolbar {
return new Toolbar(this);
}

Expand All @@ -283,7 +326,61 @@ export class Participant {
*
* @returns {Filmstrip}
*/
getFilmstrip() {
getFilmstrip(): Filmstrip {
return new Filmstrip(this);
}

/**
* Returns the participants pane.
*
* @returns {ParticipantsPane}
*/
getParticipantsPane(): ParticipantsPane {
return new ParticipantsPane(this);
}

/**
* Returns the videoQuality Dialog.
*
* @returns {VideoQualityDialog}
*/
getVideoQualityDialog(): VideoQualityDialog {
return new VideoQualityDialog(this);
}

/**
* Switches to the iframe API context
*/
async switchToAPI() {
await this.driver.switchFrame(null);
}

/**
* Switches to the meeting page context.
*/
async switchInPage() {
const mainFrame = this.driver.$('iframe');

await this.driver.switchFrame(mainFrame);
}

/**
* Returns the iframe API for this participant.
*/
getIframeAPI() {
return new IframeAPI(this);
}

/**
* Returns the local display name.
*/
async getLocalDisplayName() {
const localVideoContainer = this.driver.$('span[id="localVideoContainer"]');

await localVideoContainer.moveTo();

const localDisplayName = localVideoContainer.$('span[id="localDisplayName"]');

return await localDisplayName.getText();
}
}
Loading

0 comments on commit b901717

Please sign in to comment.