Java tutorial
/* * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jitsi.meet.test.util; import org.openqa.selenium.*; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.interactions.*; import org.openqa.selenium.support.ui.*; import java.util.*; import static org.junit.Assert.*; /** * Class contains utility operations specific to jitsi-meet user interface. * * @author Pawel Domas * @author Damian Minkov */ public class MeetUIUtils { /** * Check if on the large video there is "grey" avatar displayed and if not * fails the current test. The check consists of 3 steps: * 1. check if the "user is having networking issues" message is displayed * on the large video(with 2 seconds timeout). * 2. Check if the avatar is displayed on the large video * (with 2 seconds timeout) * 3. Verify that the large video HTML video element is hidden(with 2 * seconds timeout). * 4. Checks if the avatar has the grey filter class applied. * @param where the <tt>WebDriver</tt> instance of the participant where * the check will be performed. */ public static void assertGreyAvatarOnLarge(WebDriver where) { String largeVideoXPath = "//video[@id='largeVideo' and @class='remoteVideoProblemFilter']"; String largeAvatarXPath = "//div[@id='dominantSpeaker']"; String userDisconnectedMsgXPath = "//div[@id='largeVideoContainer']" + "/span[@id='remoteConnectionMessage']"; // Check if the message is displayed TestUtils.waitForDisplayedElementByXPath(where, userDisconnectedMsgXPath, 2); // Avatar is displayed TestUtils.waitForDisplayedElementByXPath(where, largeAvatarXPath, 2); // but video is not TestUtils.waitForNotDisplayedElementByXPath(where, largeVideoXPath, 2); // Check if the avatar is "grey" WebElement avatarElement = where.findElement(By.xpath(largeAvatarXPath)); String avatarClass = avatarElement.getAttribute("class"); assertTrue("Avatar on large video is not \"grey\": " + avatarClass, avatarClass.contains("remoteVideoProblemFilter")); } /** * Checks whether the video thumbnail for given {@code peer} has "grey" * avatar currently displayed(which means that the user is having * connectivity issues and no video was rendered). If the verification fails * the currently running test will fail. * * @param observer the <tt>WebDriver</tt> instance where the check will * be performed. * @param peer the <tt>WebDriver</tt> instance of the participant whose * video thumbnail will be verified. */ public static void assertGreyAvatarDisplayed(WebDriver observer, WebDriver peer) { String resource = MeetUtils.getResourceJid(peer); String avatarXPath = "//span[@id='participant_" + resource + "']/img[@class='userAvatar videoThumbnailProblemFilter']"; // Avatar image TestUtils.waitForDisplayedElementByXPath(observer, avatarXPath, 5); // User's video if available should be hidden TestUtils.waitForElementNotPresentOrNotDisplayedByXPath(observer, "//span[@id='participant_" + resource + "']/video", 5); } /** * Checks if the video thumbnail for given <tt>peer</tt> is currently * displaying grey video. Which means that the user's media connection is * interrupted, but at the time when it happened we had some image rendered * and can apply grey filter on top. If the check does not succeed withing * 3 seconds the currently running test will fail. * * @param observer the <tt>WebDriver</tt> where the check wil be performed. * @param peer the <tt>WebDriver</tt> instance of the user who whose * thumbnail is to be verified. */ public static void assertGreyVideoThumbnailDisplayed(WebDriver observer, WebDriver peer) { String peerId = MeetUtils.getResourceJid(peer); assertNotNull(peerId); String greyVideoXPath = "//span[@id='participant_" + peerId + "']/video[@class='videoThumbnailProblemFilter']"; TestUtils.waitForDisplayedElementByXPath(observer, greyVideoXPath, 3); } /** * Checks if the large video is displaying with the grey filter on top. * Which means that the user currently displayed is having connectivity * issues. * * @param where the <tt>WebDriver</tt> instance where the check will be * performed. */ public static void assertLargeVideoIsGrey(WebDriver where) { String largeVideoXPath = "//video[@id='largeVideo' and @class='remoteVideoProblemFilter']"; String largeAvatarXPath = "//div[@id='dominantSpeaker']"; String userDisconnectedMsgXPath = "//div[@id='largeVideoContainer']" + "/span[@id='remoteConnectionMessage']"; // 2 seconds timeout on each check int timeout = 2; // Large video TestUtils.waitForDisplayedElementByXPath(where, largeVideoXPath, timeout); // Avatar should not be visible TestUtils.waitForNotDisplayedElementByXPath(where, largeAvatarXPath, timeout); // Check if the message is displayed TestUtils.waitForDisplayedElementByXPath(where, userDisconnectedMsgXPath, timeout); } /** * Checks if the large video is displayed without the grey scale filter * applied on top. * * @param where the <tt>WebDriver</tt> instance where the check will be * performed. */ public static void assertLargeVideoNotGrey(WebDriver where) { final String largeVideoXPath = "//video[@id='largeVideo']"; String largeAvatarXPath = "//div[@id='dominantSpeaker']"; String userDisconnectedMsgXPath = "//div[@id='largeVideoContainer']" + "/span[@id='remoteConnectionMessage']"; // For not displayed we have to wait for key frame sometimes, // before the video resumes int timeout = 2; // Large video TestUtils.waitForCondition(where, 5, new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver webDriver) { WebElement el = webDriver.findElement(By.xpath(largeVideoXPath)); return !el.getAttribute("class").contains("remoteVideoProblemFilter"); } }); // Check if the message is displayed TestUtils.waitForDisplayedOrNotByXPath(where, userDisconnectedMsgXPath, timeout, false); // Avatar should not be visible TestUtils.waitForNotDisplayedElementByXPath(where, largeAvatarXPath, timeout); } /** * Shows the toolbar and clicks on a button identified by ID. * @param participant the {@code WebDriver}. * @param buttonID the id of the button to click. * @param failOnMissing whether to fail if button is missing */ public static void clickOnToolbarButton(WebDriver participant, String buttonID, boolean failOnMissing) { try { WebElement button = participant.findElement(By.xpath("//a[@id='" + buttonID + "']")); // if element missing and we do not want fail continue if (!failOnMissing && (button == null || !button.isDisplayed())) return; button.click(); } catch (NoSuchElementException e) { if (failOnMissing) throw e; // there is no element, so its not visible, just continue // cause failOnMissing is false System.err.println("Button is missing:" + buttonID); } } /** * Shows the toolbar and clicks on a button identified by ID. * @param participant the {@code WebDriver}. * @param buttonID the id of the button to click. */ public static void clickOnToolbarButton(WebDriver participant, String buttonID) { clickOnToolbarButton(participant, buttonID, true); } /** * Shows the toolbar and clicks on a button identified by class name. * @param participant the {@code WebDriver}. * @param buttonClass the class of the button to click. */ public static void clickOnToolbarButtonByClass(WebDriver participant, String buttonClass) { participant.findElement(By.xpath("//a[@class='button " + buttonClass + "']")).click(); } /** * Returns resource part of the JID of the user who is currently displayed * in the large video area in {@code participant}. * * @param participant <tt>WebDriver</tt> of the participant. * @return the resource part of the JID of the user who is currently * displayed in the large video area in {@code participant}. */ public static String getLargeVideoResource(WebDriver participant) { return (String) ((JavascriptExecutor) participant).executeScript("return APP.UI.getLargeVideoID();"); } /** * Returns <video> element for the local video. * @param participant the <tt>WebDriver</tt> from which local video element * will be obtained. * @return <tt>WebElement</tt> of the local video. */ public static WebElement getLocalVideo(WebDriver participant) { List<WebElement> peerThumbs = participant .findElements(By.xpath("//video[starts-with(@id, 'localVideo_')]")); return peerThumbs.get(0); } /** * Get's the id of local video element. * @param participant the <tt>WebDriver</tt> instance of the participant for * whom we want to obtain local video element's ID * @return a <tt>String</tt> with the ID of the local video element. */ public static String getLocalVideoID(WebDriver participant) { return getLocalVideo(participant).getAttribute("id"); } /** * Returns all remote video elements for given <tt>WebDriver</tt> instance. * @param participant the <tt>WebDriver</tt> instance which will be used to * obtain remote video elements. * @return a list of <tt>WebElement</tt> with the remote videos. */ public static List<WebElement> getRemoteVideos(WebDriver participant) { return participant.findElements(By.xpath("//video[starts-with(@id, 'remoteVideo_')]")); } /** * Obtains the ids for all remote participants <video> elements. * @param participant the <tt>WebDriver</tt> instance for which remote video * ids will be fetched. * @return a list of <tt>String</tt> with the ids of remote participants * video elements. */ public static List<String> getRemoteVideoIDs(WebDriver participant) { List<WebElement> remoteThumbs = getRemoteVideos(participant); List<String> ids = new ArrayList<>(); for (WebElement thumb : remoteThumbs) { ids.add(thumb.getAttribute("id")); } return ids; } /** * Displays film strip, if not displayed. * * @param participant <tt>WebDriver</tt> instance of the participant for * whom we'll try to open the settings panel. * @throws TimeoutException if we fail to open the settings panel. */ public static void displayFilmStripPanel(WebDriver participant) { String filmStripXPath = "//div[@id='remoteVideos' and @class='hidden']"; WebElement filmStrip; try { filmStrip = participant.findElement(By.xpath(filmStripXPath)); } catch (NoSuchElementException ex) { filmStrip = null; } if (filmStrip != null) { clickOnToolbarButton(participant, "toolbar_film_strip"); TestUtils.waitForElementNotPresentByXPath(participant, filmStripXPath, 5); } } /** * Opens the settings panel, if not open. * * @param participant <tt>WebDriver</tt> instance of the participant for * whom we'll try to open the settings panel. * @throws TimeoutException if we fail to open the settings panel. */ public static void displaySettingsPanel(WebDriver participant) { String settingsXPath = "//div[@id='settings_container']"; WebElement settings = participant.findElement(By.xpath(settingsXPath)); if (!settings.isDisplayed()) { clickOnToolbarButton(participant, "toolbar_button_settings"); TestUtils.waitForDisplayedElementByXPath(participant, settingsXPath, 5); } } /** * Hides the settings panel, if not hidden. * * @param participant <tt>WebDriver</tt> instance of the participant for * whom we'll try to hide the settings panel. * @throws TimeoutException if we fail to hide the settings panel. */ public static void hideSettingsPanel(WebDriver participant) { String settingsXPath = "//div[@id='settings_container']"; WebElement settings = participant.findElement(By.xpath(settingsXPath)); if (settings.isDisplayed()) { clickOnToolbarButton(participant, "toolbar_button_settings"); TestUtils.waitForNotDisplayedElementByXPath(participant, settingsXPath, 5); } } /** * Opens the contact list panel, if not open. * * @param participant <tt>WebDriver</tt> instance of the participant for * whom we'll try to open the contact list panel. * @throws TimeoutException if we fail to open the contact list panel */ public static void displayContactListPanel(WebDriver participant) { String contactListXPath = "//div[@id='contacts_container']"; WebElement contactList = participant.findElement(By.xpath(contactListXPath)); if (!contactList.isDisplayed()) { clickOnToolbarButton(participant, "toolbar_contact_list"); TestUtils.waitForDisplayedElementByXPath(participant, contactListXPath, 5); } // move away from the button as user will do, to remove the tooltips Actions action = new Actions(participant); action.moveToElement(participant.findElement(By.id("largeVideoWrapper"))); action.perform(); } /** * Asserts that {@code participant} shows or doesn't show the audio or * video mute icon for the conference participant identified by * {@code resource}. * * @param name the name that will be displayed in eventual failure message. * @param observer the {@code WebDriver} where the check will be * performed. * @param testee the <tt>WebDriver</tt> of the participant for whom we're * checking the status of audio muted icon. * @param isMuted if {@code true}, the method will assert the presence of * the "mute" icon; otherwise, it will assert its absence. * @param isVideo if {@code true} the icon for "video mute" will be checked; * otherwise, the "audio mute" icon will be checked. */ public static void assertMuteIconIsDisplayed(WebDriver observer, WebDriver testee, boolean isMuted, boolean isVideo, String name) { String id = ""; if (testee != observer) { String resource = MeetUtils.getResourceJid(testee); id = "participant_" + resource; } else { id = "localVideoContainer"; } String icon = isVideo ? TestUtils.getXPathStringForClassName("//span", "videoMuted") + "/i[@class='icon-camera-disabled']" : TestUtils.getXPathStringForClassName("//span", "audioMuted") + "/i[@class='icon-mic-disabled']"; String mutedIconXPath = "//span[@id='" + id + "']" + icon; try { if (isMuted) { TestUtils.waitForElementByXPath(observer, mutedIconXPath, 5); } else { TestUtils.waitForElementNotPresentOrNotDisplayedByXPath(observer, mutedIconXPath, 5); } } catch (TimeoutException exc) { fail(name + (isMuted ? " should" : " shouldn't") + " be muted at this point, xpath: " + mutedIconXPath); } } /** * For for the peer to have his audio muted/unmuted from given observer's * perspective. The method will fail the test if something goes wrong or * the audio muted status is different than the expected one. We wait up to * 3 seconds for the expected status to appear. * * @param observer <tt>WebDriver</tt> instance of the participant that * observes the audio status * @param testee <tt>WebDriver</tt> instance of the peer for whom we're * checking the audio muted status. * @param testeeName the name of the testee that will be printed in failure * logs * @param muted <tt>true</tt> to wait for audio muted status or * <tt>false</tt> to wait for the peer to unmute. */ public static void waitForAudioMuted(final WebDriver observer, final WebDriver testee, final String testeeName, final boolean muted) { // Waits for the correct icon assertMuteIconIsDisplayed(observer, testee, muted, false, //audio testeeName); // The code below check verifies audio muted status by checking peer's // audio levels on the oberver side. Statistics support is required to // do that if (!MeetUtils.areRtpStatsSupported(observer)) return; // Give it 3 seconds to not get any audio or to receive some // depending on "muted" argument try { TestUtils.waitForCondition(observer, 3, new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver webDriver) { Double audioLevel = MeetUtils.getPeerAudioLevel(webDriver, testee); // NOTE: audioLevel == null also when it is 0 // When testing for muted we want audio level to stay // 'null' or 0, so we wait to timeout this condition if (muted) { if (audioLevel != null && audioLevel > 0.1) { System.err.println("muted exiting on: " + audioLevel); return true; } else { return false; } } // When testing for unmuted we wait for first sound else { if (audioLevel != null && audioLevel > 0.1) { System.err.println("unmuted exiting on: " + audioLevel); return true; } else { return false; } } } }); // When testing for muted we don't want to have // the condition succeeded if (muted) { fail("There was some sound coming from muted: '" + testeeName + "'"); } // else we're good for unmuted peer } catch (TimeoutException timeout) { if (!muted) { fail("There was no sound from unmuted: '" + testeeName + "'"); } // else we're good for muted peer } } /** * Makes sure that a user's avatar is displayed, and that the user's video * is not displayed. Allows for the these conditions to not hold * immediately, but within a time interval of 5 seconds. * @param participant instance of <tt>WebDriver</tt> on which we'll perform * the verification. * @param resource the resource part of MUC JID which identifies user's * video thumbnail. */ public static void assertAvatarDisplayed(WebDriver participant, String resource) { // Avatar image TestUtils.waitForDisplayedElementByXPath(participant, "//span[@id='participant_" + resource + "']" + "/img[@class='userAvatar']", 5); // User's video if available should be hidden, the element is missing // if remote participant started muted when we joined String videoElementXPath = "//span[@id='participant_" + resource + "']/video"; List<WebElement> videoElems = participant.findElements(By.xpath(videoElementXPath)); if (videoElems.size() > 0) { TestUtils.waitForNotDisplayedElementByXPath(participant, videoElementXPath, 5); } } /** * A method overload for * {@link #assertDisplayNameVisible(WebDriver, String)} which does * automatically obtain the "resource JID" from the participant's * <tt>WebDriver</tt> instance. * @param where instance of <tt>WebDriver</tt> on which we'll perform * the verification. * @param whose the <tt>WebDriver</tt> instance of the participant to whom * the video thumbnail being checked belongs to. */ public static void assertDisplayNameVisible(WebDriver where, WebDriver whose) { String resourceJid = MeetUtils.getResourceJid(whose); assertDisplayNameVisible(where, resourceJid); } /** * Makes sure that a user's display name is displayed, and that * the user's thumbnail and avatar are not displayed. Allows for the these * conditions to not hold immediately, but within a time interval of 5 * seconds. * @param participant instance of <tt>WebDriver</tt> on which we'll perform * the verification. * @param resource the resource part of MUC JID which identifies user's * video thumbnail. */ public static void assertDisplayNameVisible(WebDriver participant, String resource) { // Avatar image - hidden TestUtils.waitForNotDisplayedElementByXPath(participant, "//span[@id='participant_" + resource + "']" + "/img[contains(@class, 'userAvatar')]", 5); // User's video - hidden, if it is available String videoElementXPath = "//span[@id='participant_" + resource + "']/video"; List<WebElement> videoElems = participant.findElements(By.xpath(videoElementXPath)); if (videoElems.size() > 0) { TestUtils.waitForNotDisplayedElementByXPath(participant, videoElementXPath, 5); } // Display name - visible TestUtils.waitForDisplayedElementByXPath(participant, "//span[@id='participant_" + resource + "']" + "//span[@class='displayname']", 5); } /** * Clicks on a given participant's (identified by the resource part of it's * JID) video thumbnail. * @param participant instance of <tt>WebDriver</tt> where we'll perform the * click. * @param resourceJid the resource part of MUC JID which identifies user's * video thumbnail. */ public static void clickOnRemoteVideo(WebDriver participant, String resourceJid) { participant.findElement(By.xpath("//span[@id='participant_" + resourceJid + "']")).click(); } /** * Clicks on the local video thumbnail. * @param participant the instance of <tt>WebDriver</tt> where we'll * perform the click. */ public static void clickOnLocalVideo(WebDriver participant) { TestUtils.executeScript(participant, "document.getElementById('localVideoContainer').click()"); } /** * Makes sure that the local video is displayed in the local thumbnail and * that the avatar is not displayed. * @param participant the instance of <tt>WebDriver</tt> on which we'll * perform the verification. */ public static void assertLocalThumbnailShowsVideo(WebDriver participant) { TestUtils.waitForNotDisplayedElementByXPath(participant, "//span[@id='localVideoContainer']/img[@class='userAvatar']", 5); TestUtils.waitForDisplayedElementByXPath(participant, "//span[@id='localVideoWrapper']/video", 5); } /** * Makes sure that the avatar is displayed in the local thumbnail and that * the video is not displayed. * @param participant the instance of <tt>WebDriver</tt> on which we'll * perform the verification. */ public static void assertLocalThumbnailShowsAvatar(WebDriver participant) { TestUtils.waitForDisplayedElementByXPath(participant, "//span[@id='localVideoContainer']/img[@class='userAvatar']", 5); TestUtils.waitForElementNotPresentOrNotDisplayedByXPath(participant, "//span[@id='localVideoWrapper']/video", 5); } /** * Returns the source of the large video currently shown. * @return the source of the large video currently shown. */ public static String getLargeVideoID(WebDriver driver) { WebElement videoElement = driver.findElement(By.id("largeVideo")); return getVideoElementID(driver, videoElement); } /** * Checks whether the large video has changed to the desired resource. * @param driver the driver to check * @param resource the expected resource */ public static void waitsForLargeVideoSwitch(WebDriver driver, final String resource) { TestUtils.waitForCondition(driver, 5, new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return resource.equals(getLargeVideoResource(d)); } }); } /** * Returns the identifier of the video element. * * @param driver the driver * @param element the video element * @return unique identifier. */ public static String getVideoElementID(WebDriver driver, WebElement element) { Object res = ((JavascriptExecutor) driver).executeScript("var el = arguments[0]; " + "var srcObject = el.srcObject || el.mozSrcObject;" + "return srcObject? srcObject.id : el.src;", element); return (String) res; } /** * Returns list of participant's thumbnails. * @param participant the instance of <tt>WebDriver</tt> * @return list of thumbnails <tt>WebElement</tt> elements */ public static List<WebElement> getThumbnails(WebDriver participant) { return participant .findElements(By.xpath("//div[@id='remoteVideos']/span[contains(@class,'videocontainer')]")); } /** * Returns list of currently visible participant's thumbnails. * @param participant the instance of <tt>WebDriver</tt> * @return list of thumbnails <tt>WebElement</tt> elements */ public static List<WebElement> getVisibleThumbnails(WebDriver participant) { List<WebElement> thumbnails = getThumbnails(participant); Iterator<WebElement> it = thumbnails.iterator(); while (it.hasNext()) { WebElement thumb = it.next(); if (!thumb.isDisplayed()) { it.remove(); } } return thumbnails; } /** * Checks if observer's active speaker is testee. * @param observer <tt>WebDriver</tt> instance of the participant that * should check active speaker. * @param testee <tt>WebDriver</tt> instance of the peer for may be * active speaker for the observer. * @return <tt>true</tt> true if observer's active speaker is testee, * <tt>false</tt> otherwise. */ public static boolean isActiveSpeaker(WebDriver observer, WebDriver testee) { final String expectedJid = MeetUtils.getResourceJid(testee); try { TestUtils.waitForCondition(observer, 5, new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { String currentJid = MeetUIUtils.getLargeVideoResource(d); return expectedJid.equals(currentJid); } }); return true; } catch (TimeoutException ignored) { return false; } } /** * Asserts that observer shows the audio mute icon for the testee. * * @param observer <tt>WebDriver</tt> instance of the participant that * observes the audio status * @param testee <tt>WebDriver</tt> instance of the peer for whom we're * checking the audio muted status. * @param testeeName the name of the testee that will be printed in failure * logs */ public static void assertAudioMuted(WebDriver observer, WebDriver testee, String testeeName) { MeetUIUtils.assertMuteIconIsDisplayed(observer, testee, true, //should be muted false, //audio testeeName); } /** * Click on the local video thumbnail and waits until it's displayed on * "the large video". * * @param where the <tt>WebDriver</tt> instance on which the action is to * be performed. */ static public void selectLocalVideo(WebDriver where) { // click on local MeetUIUtils.clickOnLocalVideo(where); WebElement localVideoElem = where.findElement(By.xpath("//span[@id='localVideoWrapper']/video")); final String largeVideoID = MeetUIUtils.getVideoElementID(where, localVideoElem); waitForLargeVideoSwitch(where, largeVideoID); } /** * Selects the remote video to be displayed on "the large video" by clicking * participant's video thumbnail and waits for the switch to take place * using {@link #waitForLargeVideoSwitch(WebDriver, String)}. * * @param where the <tt>WebDriver</tt> instance on which the selection will * be performed. * @param toBeSelected the <tt>WebDriver</tt> instance which belongs to * the participant that is to be displayed on "the large video". Is used to * obtain user's identifier. */ static public void selectRemoteVideo(WebDriver where, WebDriver toBeSelected) { String resourceJid = MeetUtils.getResourceJid(toBeSelected); String remoteThumbXpath = "//span[starts-with(@id, 'participant_" + resourceJid + "') " + " and contains(@class,'videocontainer')]"; String remoteThumbVideoXpath = remoteThumbXpath + "/video[starts-with(@id, 'remoteVideo_')]"; WebElement remoteThumbnail = TestUtils.waitForElementByXPath(where, remoteThumbXpath, 5, "Remote thumbnail not found: " + remoteThumbXpath); // click on remote remoteThumbnail.click(); WebElement remoteThumbnailVideo = TestUtils.waitForElementByXPath(where, remoteThumbVideoXpath, 5, "Remote video not found: " + remoteThumbVideoXpath); String videoSrc = getVideoElementID(where, remoteThumbnailVideo); waitForLargeVideoSwitch(where, videoSrc); } /** * Sets an attribute on an element * @param element the element * @param attributeName the attribute name to set * @param attributeValue the value to set */ public static void setAttribute(WebDriver driver, WebElement element, String attributeName, String attributeValue) { ((JavascriptExecutor) driver).executeScript("arguments[0][arguments[1]] = arguments[2];", element, attributeName, attributeValue); } /** * Waits up to 3 seconds for the large video update to happen. * * @param where the <tt>WebDriver</tt> instance where the large video update * will be performed. * @param expectedVideoSrc a string which identifies the video stream * (the source set on HTML5 video element to attach WebRTC media stream). */ static private void waitForLargeVideoSwitch(WebDriver where, final String expectedVideoSrc) { new WebDriverWait(where, 3).withMessage("Failed to switch the large video at: " + MeetUtils.getResourceJid(where) + " to : " + expectedVideoSrc) .until(new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver where) { return expectedVideoSrc.equals(MeetUIUtils.getLargeVideoID(where)); } }); } /** * Verifies the UI indication of remote participant's media connection * status. If the verification fails the currently running test will fail. * * @param observer the <tt>WebDriver</tt> instance where the check will be * performed. * @param peer the <tt>WebDriver</tt> of the participant whose connection * status will be checked. * @param isConnected tells whether the check is for * connected(<tt>true</tt>) or disconnected(<tt>false</tt>). */ public static void verifyUserConnStatusIndication(WebDriver observer, WebDriver peer, boolean isConnected) { String peerId = MeetUtils.getResourceJid(peer); assertNotNull(peerId); // may take time for the video to recover(key frame) than disrupt int timeout = isConnected ? 60 : 15; // Wait for the logic to tell that the user is disconnected TestUtils.waitForBoolean(observer, MeetUtils.isConnectionActiveScript(peerId, isConnected), timeout); // Check connection status indicators String connectionLostXpath = "//span[@id='participant_" + peerId + "']//span[@class='connection_lost']"; // Check "connection lost" icon TestUtils.waitForDisplayedOrNotByXPath(observer, connectionLostXpath, 2, !isConnected); } /** * Verifies the UI indication of local media connection status. If * the verification fails the currently running test will fail. * * @param where the <tt>WebDriver</tt> instance where the check will be * performed. * @param isConnected tells whether the check is for * connected(<tt>true</tt>) or disconnected(<tt>false</tt>). */ public static void verifyLocalConnStatusIndication(WebDriver where, boolean isConnected) { // Wait for the logic to reflect the status first TestUtils.waitForBoolean(where, MeetUtils.isLocalConnectionActiveScript(isConnected), 15); // Check connection status indicators String connectionLostXpath = "//span[@id='localVideoContainer']" + "//span[@class='connection_lost']"; // Check "connection lost" icon TestUtils.waitForDisplayedOrNotByXPath(where, connectionLostXpath, 3, !isConnected); } }