/*******************************************************************************
* ATE, Automation Test Engine
*
* Copyright 2015, Montreal PROT, or individual contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Montreal PROT.
*
* 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.bigtester.ate.model.page.atewebdriver; //NOPMD
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.bigtester.ate.GlobalUtils;
import org.bigtester.ate.model.casestep.ITestCase;
import org.bigtester.ate.model.page.atewebdriver.exception.BrowserUnexpectedException;
import org.eclipse.jdt.annotation.Nullable;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.UnreachableBrowserException;
import org.openqa.selenium.support.events.WebDriverEventListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.util.StringUtils;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
// TODO: Auto-generated Javadoc
/**
* This class BrowserWindowsMonitor defines ....
*
* @author Peidong Hu
*
*/
public class MultiWindowsHandler extends AbstractLockProtectedMultiWindowsHandler implements IMultiWindowsHandler,
WebDriverEventListener, ApplicationListener<AlertDialogAcceptedEvent> {
/** The test case. */
@Nullable
@Autowired
private ITestCase testCase;
/**
* Gets the window on focus handle.
*
* @return the window on focus handle
*/
@Nullable
public String getWindowOnFocusHandle() {
String retVal;
if (getWindows().isEmpty()) {
retVal = null; // NOPMD
} else {
retVal = getDriver().getWindowHandle();
}
return retVal;
}
/**
* {@inheritDoc}
*/
@Nullable
public BrowserWindow getWindowByHandle(String winHandle) {
BrowserWindow retVal = null;//NOPMD
for (BrowserWindow win : this.getWindows()) {
if (winHandle.equalsIgnoreCase(win.getWindowHandle())) {
retVal = win;
break;
}
}
return retVal;
}
/**
* Close window.
*
* @param winHandle
* the win handle
* @throws BrowserUnexpectedException
*/
public void closeWindow(String winHandle) throws BrowserUnexpectedException {
BrowserWindow closingWindow = getWindowByHandle(winHandle);
if (null == closingWindow) {
// if (winHandle.equals(getWindowOnFocusHandle())) {
// getDriver().close();
// } else {
// getDriver().switchTo().window(winHandle);
// getDriver().close();
// }
throw GlobalUtils.createNotInitializedException("windows");
} else {
closingWindow.close();
try {
// test if there is alert. if no, refresh windows list
checkCloseWindowAlert(closingWindow.getWindowHandle());
closingWindow.setClosed(false);
} catch (NoAlertPresentException noAlert) {
if (getNumberOfOpenWindows() > 0)
refreshWindowsList(getDriver(), false);
}
}
}
private int getNumberOfOpenWindows() {
int retVal = 0;//NOPMD
for (BrowserWindow win : getWindows()) {
if (!win.isClosed())
retVal = retVal + 1;
}
return retVal;
}
private void checkCloseWindowAlert(String winh)
throws NoAlertPresentException {
try {
Alert alt = getDriver().switchTo().alert();
if (alt == null)
throw GlobalUtils.createInternalError("web driver");
PopupPromptDialog aDialog = new PopupPromptDialog(getDriver(), alt,
alerts.size());
aDialog.setClosingWindowHandle(winh);
alerts.add(aDialog);
} catch (UnreachableBrowserException error) {
if (getNumberOfOpenWindows() > 0)
throw GlobalUtils
.createInternalError("ATE multi windows handler", error);
} catch (UnsupportedOperationException e) {
throw GlobalUtils
.createInternalError("Driver doesn't support alert handling yet", e);
} catch (NoSuchWindowException windClosedAlready) {
//do nothing if window closed without alert dialog intervention. for example in Chrome.
throw new NoAlertPresentException(windClosedAlready);
}
}
/**
* Close all windows except main window.
* @throws BrowserUnexpectedException
*/
public void closeAllWindowsExceptMainWindow() throws BrowserUnexpectedException {
closeAllOtherWindows(getMainWindowHandler());
}
/**
* Retrieve current window title.
*
* @return the string
*/
final public String retrieveCurrentWindowTitle() {
String windowTitle = getDriver().getTitle();
if (null == windowTitle) {
throw GlobalUtils.createInternalError("web driver internal error!");
} else {
return windowTitle;
}
}
// To close all the other windows except the main window.
/**
* Close all other windows.
*
* @param openWindowHandle
* the open window handle
* @return true, if successful
* @throws BrowserUnexpectedException
*/
public boolean closeAllOtherWindows(String openWindowHandle) throws BrowserUnexpectedException {
Iterator<BrowserWindow> itr = this.getWindows().iterator();
while(itr.hasNext()) {
BrowserWindow win = itr.next();
//for (BrowserWindow win : this.getWindows()) {
if (!openWindowHandle.equalsIgnoreCase(win.getWindowHandle())) {
win.close();
try {
checkCloseWindowAlert(win.getWindowHandle());// test if there is alert. if no, refresh windows list
} catch (NoAlertPresentException noAlert) {
refreshWindowsList(getDriver(), false);
if (this.getWindows().size()>1)
itr = this.getWindows().iterator();
else
break;
}
}
}
// deal with the windows not in the windows list
Set<String> allWindowHandles = getDriver().getWindowHandles();
for (String currentWindowHandle : allWindowHandles) {
if (!currentWindowHandle.equals(openWindowHandle)) {
getDriver().switchTo().window(currentWindowHandle);
getDriver().close();
try {
// test if there is alert. if no, refresh windows list
checkCloseWindowAlert(currentWindowHandle);
} catch (NoAlertPresentException noAlert) {
refreshWindowsList(getDriver(), false);
}
}
}
getDriver().switchTo().window(openWindowHandle);
boolean retVal;
if (getDriver().getWindowHandles().size() == 1) { // NOPMD
retVal = true;
} else {
retVal = false;
}
return retVal;
}
/**
* Switch to window.
*
* @param title
* the title
* @return true, if successful
*/
public boolean switchToWindowUsingTitle(String title) {
String currentWindow = getDriver().getWindowHandle(); // NOPMD
Set<String> availableWindows = getDriver().getWindowHandles();
boolean switchSuccess;
if (availableWindows.isEmpty()) {
switchSuccess = false;
} else {
switchSuccess = false; // NOPMD
for (String windowId : availableWindows) {
if (getDriver().switchTo().window(windowId).getTitle()
.equals(title)) {
switchSuccess = true;
break;
} else {
getDriver().switchTo().window(currentWindow);
}
}
}
return switchSuccess;
}
/**
* Retrive window handle using title.
*
* @param title
* the title
* @return the string
*/
@Nullable
public String retriveWindowHandleUsingTitle(String title) {
String currentWindow = getDriver().getWindowHandle(); // NOPMD
Set<String> availableWindows = getDriver().getWindowHandles();
String retVal = null; // NOPMD
if (!availableWindows.isEmpty()) {
for (String windowId : availableWindows) {
if (getDriver().switchTo().window(windowId).getTitle()
.equals(title)) {
retVal = getDriver().getWindowHandle();
break;
} else {
getDriver().switchTo().window(currentWindow);
}
}
}
return retVal;
}
/**
* Focus on latest window.
*/
public void focusOnLatestWindow() {
if (getWindows().isEmpty())
return;
getWindows().get(getWindows().size() - 1).obtainWindowFocus();
}
/**
* Obtain window handle.
*
* @param openSequence
* the open sequence
* @return the string
*/
@Nullable
public String obtainWindowHandle(int openSequence) {
try {
this.refreshWindowsList(getDriver(), false);
} catch (BrowserUnexpectedException e) {
this.retryRefreshWindows(getDriver(), false);
}
String retVal = null; // NOPMD
if (getWindows().size() >= openSequence + 1) {
retVal = getWindows().get(openSequence).getWindowHandle();
}
return retVal;
}
/**
* Obtain focus on alert dialog.
*
* @param openSequence
* the open sequence, indexed from 0
* @return the abstract alert dialog
*/
@Nullable
public AbstractAlertDialog obtainFocusOnAlertDialog(int openSequence) {
AbstractAlertDialog retVal;
if (alerts.isEmpty())
retVal = null;//NOPMD
else {
if (openSequence >= alerts.size())
throw GlobalUtils
.createNotInitializedException("this alert, opensequence is too large");
retVal = alerts.get(openSequence);
if (null == retVal)
throw GlobalUtils.createInternalError("java");
}
return retVal;
}
/**
* Obtain focus on latest alert dialog.
*
* @return the abstract alert dialog
*/
@Nullable
public AbstractAlertDialog obtainFocusOnLatestAlertDialog() {
AbstractAlertDialog retVal;
if (alerts.isEmpty())
retVal = null;//NOPMD
else {
retVal = alerts.get(alerts.size() - 1);
if (null == retVal)
throw GlobalUtils.createInternalError("java");
}
return retVal;
}
/**
* Focus on open sequence number.
*
* @param openSequence
* the open sequence
*/
public void focusOnOpenSequenceNumber(int openSequence) {
if (getWindows().size() < openSequence + 1) {
return;
} else {
getWindows().get(openSequence).obtainWindowFocus();
}
}
/**
* Gets the browser window on focus.
*
* @return the browser window on focus
*/
public BrowserWindow getBrowserWindowOnFocus() {
String winHandle = this.getDriver().getWindowHandle(); // NOPMD
for (BrowserWindow bwd : getWindows()) {
if (bwd.getWindowHandle().equals(winHandle)) {
return bwd;
}
}
throw GlobalUtils.createInternalError("web driver wrong state");
}
/**
* {@inheritDoc}
*/
@Override
public void afterChangeValueOf(@Nullable WebElement arg0,
@Nullable WebDriver arg1) {
try {
refreshWindowsList(arg1, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
public void retryRefreshWindows(WebDriver driver, boolean refreshFrames) {
this.resetWindows();
try {
refreshWindowsList(driver, refreshFrames);
} catch (BrowserUnexpectedException e1) {
throw GlobalUtils.createInternalError("browser fatal error.", e1);//NOPMD
}
}
/**
* {@inheritDoc}
*/
@Override
public void afterClickOn(@Nullable WebElement arg0, @Nullable WebDriver arg1) {
try {
refreshWindowsList(arg1, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void afterFindBy(@Nullable By arg0, @Nullable WebElement arg1,
@Nullable WebDriver arg2) {
// refreshWindowsList(arg2);
}
/**
* {@inheritDoc}
*/
@Override
public void afterNavigateBack(@Nullable WebDriver arg0) {
try {
refreshWindowsList(arg0, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void afterNavigateForward(@Nullable WebDriver arg0) {
try {
refreshWindowsList(arg0, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void afterNavigateTo(@Nullable String arg0, @Nullable WebDriver arg1) {
try {
refreshWindowsList(arg1, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void afterScript(@Nullable String arg0, @Nullable WebDriver arg1) {
try {
refreshWindowsList(arg1, false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void beforeChangeValueOf(@Nullable WebElement arg0,
@Nullable WebDriver arg1) {
// refreshWindowsList(arg1);
}
/**
* {@inheritDoc}
*/
@Override
public void beforeClickOn(@Nullable WebElement arg0,
@Nullable WebDriver arg1) {
// refreshWindowsList(arg1);
}
/**
* {@inheritDoc}
*/
@Override
public void beforeFindBy(@Nullable By arg0, @Nullable WebElement arg1,
@Nullable WebDriver arg2) {
// try {
// refreshWindowsList(arg2, true);
// } catch (BrowserUnexpectedException e) {
// retryRefreshWindows(getMyWd().getWebDriverInstance());
// }
}
/**
* {@inheritDoc}
*/
@Override
public void beforeNavigateBack(@Nullable WebDriver arg0) {
// refreshWindowsList(arg0);
}
/**
* {@inheritDoc}
*/
@Override
public void beforeNavigateForward(@Nullable WebDriver arg0) {
// refreshWindowsList(arg0);
}
/**
* {@inheritDoc}
*/
@Override
public void beforeNavigateTo(@Nullable String arg0, @Nullable WebDriver arg1) {
// refreshWindowsList(arg1);
}
/**
* {@inheritDoc}
*/
@Override
public void beforeScript(@Nullable String arg0, @Nullable WebDriver arg1) {
// refreshWindowsList(arg1);
}
/**
* {@inheritDoc}
*/
@Override
public void onException(@Nullable Throwable arg0, @Nullable WebDriver arg1) {
// TODO Auto-generated method stub
}
/**
* {@inheritDoc}
*/
@Override
public void onApplicationEvent(@Nullable AlertDialogAcceptedEvent event) {
if (null == event)
throw GlobalUtils.createInternalError("spring event");
AbstractAlertDialog alertD = (AbstractAlertDialog) event.getSource();//NOPMD
for (int i = 0; i < getWindows().size(); i++) {
if (getWindows().get(i).getWindowHandle()
.equalsIgnoreCase(alertD.getClosingWindowHandle())) {
getWindows().get(i).setClosed(true);
try {
refreshWindowsList(this.getDriver(), false);
} catch (BrowserUnexpectedException e) {
retryRefreshWindows(getMyWd().getWebDriverInstance(), false);
}
}
}
}
/**
* @return the testCase
*/
public ITestCase getTestCase() {
final ITestCase testCase2 = testCase;
if (testCase2 == null) {
throw GlobalUtils.createNotInitializedException("test case");
} else {
return testCase2;
}
}
/**
* @param testCase the testCase to set
*/
public void setTestCase(ITestCase testCase) {
this.testCase = testCase;
}
}