/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.admingui.devtests;
import com.google.common.base.Function;
import com.thoughtworks.selenium.Selenium;
import com.thoughtworks.selenium.SeleniumException;
import org.junit.*;
import org.openqa.selenium.*;
import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.security.SecureRandom;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.glassfish.admingui.common.util.RestUtil;
import org.glassfish.admingui.devtests.util.ElementFinder;
import org.glassfish.admingui.devtests.util.SeleniumHelper;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
public class BaseSeleniumTestClass {
public static final String CURRENT_WINDOW = "selenium.browserbot.getCurrentWindow()";
public static final int TIMEOUT_CALLBACK_LOOP = 1000;
public static final String TRIGGER_NEW_VALUES_SAVED = "New values successfully saved.";
public static final String TRIGGER_COMMON_TASKS = "Common Tasks";
public static final String TRIGGER_REGISTRATION_PAGE = "Receive patch information and bug updates, screencasts and tutorials, support and training offerings, and more";
public static final String TRIGGER_ERROR_OCCURED = "An error has occurred";
public static final boolean DEBUG = Boolean.parseBoolean(SeleniumHelper.getParameter("debug", "false"));
@Rule
public SpecificTestRule specificTestRule = new SpecificTestRule();
protected static final int TIMEOUT = 90;
protected static final int BUTTON_TIMEOUT = 750;
protected static final Logger logger = Logger.getLogger(BaseSeleniumTestClass.class.getName());
protected static Selenium selenium;
protected static WebDriver driver;
private static String currentTestClass = "";
private boolean processingLogin = false;
private static final String AJAX_INDICATOR = "ajaxIndicator";
private static final Map<String, String> bundles = new HashMap<String, String>() {
{
put("i18n", "org.glassfish.admingui.core.Strings"); // core
put("i18nUC", "org.glassfish.updatecenter.admingui.Strings"); // update center
put("i18n_corba", "org.glassfish.corba.admingui.Strings");
put("i18n_ejb", "org.glassfish.ejb.admingui.Strings");
put("i18n_ejbLite", "org.glassfish.ejb-lite.admingui.Strings");
put("i18n_jts", "org.glassfish.jts.admingui.Strings"); // JTS
put("i18n_web", "org.glassfish.web.admingui.Strings"); // WEB
put("common", "org.glassfish.common.admingui.Strings");
put("i18nc", "org.glassfish.common.admingui.Strings"); // common -- apparently we use both in the app :|
put("i18nce", "org.glassfish.admingui.community-theme.Strings");
put("i18ncs", "org.glassfish.cluster.admingui.Strings"); // cluster
put("i18njca", "org.glassfish.jca.admingui.Strings"); // JCA
put("i18njdbc", "org.glassfish.jdbc.admingui.Strings"); // JDBC
put("i18njmail", "org.glassfish.full.admingui.Strings");
put("i18njms", "org.glassfish.jms.admingui.Strings"); // JMS
put("theme", "org.glassfish.admingui.community-theme.Strings");
// TODO: These conflict with core and should probably be changed in the pages
//put("i18n", "org.glassfish.common.admingui.Strings");
//put("i18n", "org.glassfish.web.admingui.Strings");
//put("i18nc", "org.glassfish.web.admingui.Strings");
}
};
private static final SeleniumHelper helper = SeleniumHelper.getInstance();
private ElementFinder elementFinder;
public BaseSeleniumTestClass() {
driver = helper.getDriver();
selenium = helper.getSeleniumInstance();
elementFinder = helper.getElementFinder();
if (Boolean.parseBoolean(SeleniumHelper.getParameter("slowDown", "false"))) {
driver.manage().timeouts().implicitlyWait(500, TimeUnit.MILLISECONDS);
}
}
@BeforeClass
public static void setUp() throws Exception {
if (!DEBUG) {
//RestUtil.post(helper.getBaseUrl() + "/management/domain/rotate-log", new HashMap<String, Object>());
}
}
@AfterClass
public static void captureLog() {
try {
helper.releaseSeleniumInstance();
if (!currentTestClass.isEmpty() && !DEBUG) {
URL url = new URL("http://localhost:" + SeleniumHelper.getParameter("admin.port", "4848") + "/management/domain/view-log");
InputStream is = url.openStream();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("target/surefire-reports/" + currentTestClass + "-server.log")));
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line = in.readLine();
while (line != null) {
out.write(line + System.getProperty("line.separator"));
line = in.readLine();
}
in.close();
out.close();
}
} catch (FileNotFoundException fnfe) {
//
} catch (Exception ex) {
Logger.getLogger(BaseSeleniumTestClass.class.getName()).log(Level.INFO, null, ex);
}
}
@Before
public void reset() {
selenium = helper.getSeleniumInstance();
currentTestClass = this.getClass().getName();
openAndWait("/", TRIGGER_COMMON_TASKS);
}
@After
public void afterTest() {
if (Boolean.parseBoolean(SeleniumHelper.getParameter("releaseAfter", "false"))) {
helper.releaseSeleniumInstance();
}
}
// *************************************************************************
// Wrappers for Selenium API
// *************************************************************************
/**
* Returns the current value for the specified field
* @see DefaultSelenium.getValue(String)
* @param elem
* @return
*/
public String getFieldValue(String elem) {
waitForElement(elem);
return selenium.getValue(elem);
}
/**
* Types the specified text into the requested element
* @param elem
* @param text
*/
public void setFieldValue(String elem, String text) {
waitForElement(elem);
selenium.focus(elem);
selenium.type(elem, text);
}
/**
* Gets the text of an element.
* @see DefaultSelenium.getText(String)
* @param elem
* @return
*/
public String getText(String elem) {
waitForElement(elem);
return selenium.getText(elem);
}
/**
* Deelects (unchecks) the specified checkbox. After calling this method, the
* checkbox will be unchecked regardless of its initial state.
* @param elem
*/
public void markCheckbox(String elem) {
waitForElement(elem);
selenium.check(elem);
}
/**
* Selects (checks) the specified checkbox. After calling this method, the
* checkbox will be checked regardless of its initial state.
* @param elem
*/
public void clearCheckbox(String elem) {
waitForElement(elem);
selenium.uncheck(elem);
}
public void pressButton(final String button) {
waitForElement(button);
new ExceptionSwallowingLoop<Void>() {
@Override
public Void operation() {
selenium.click(button);
return null;
}
}.get();
}
/**
* Return the selected value of the specified select element
* @param elem
* @return
*/
public String getSelectedValue(String elem) {
waitForElement(elem);
return selenium.getSelectedValue(elem);
}
/**
* Returns true is the specified element is present on the page
* @param elem
* @return
*/
public boolean isElementPresent(String elem) {
return selenium.isElementPresent(elem);
}
protected String captureScreenshot() {
return SeleniumHelper.captureScreenshot();
}
/**
* Select the option requested in the given select element
* @param id
* @param label
*/
protected void selectDropdownOption(String id, String label) {
try {
label = resolveTriggerText(label);
waitForElement(id);
selenium.select(id, "label="+label);
} catch (SeleniumException se) {
try {
selenium.select(id, "value=" + label);
} catch (SeleniumException se1) {
logger.log(Level.INFO, "An invalid option was requested. Here are the valid options:");
for (String option : selenium.getSelectOptions(id)) {
logger.log(Level.INFO, "\t{0}", option);
}
throw se1;
}
}
}
/**
* Add a selection to the given select element
* @param elem
* @param label
*/
protected void addSelectSelection(String elem, String label) {
try {
label = resolveTriggerText(label);
waitForElement(elem);
selenium.addSelection(elem, "label="+label);
} catch (SeleniumException se) {
logger.info("An invalid option was requested. Here are the valid options:");
for (String option : selenium.getSelectOptions(elem)) {
logger.log(Level.INFO, "\t{0}", option);
}
throw se;
}
}
/**
* Returns true if the specified checkbox is selected
* @param elem
* @return
*/
protected boolean isChecked(String elem) {
waitForElement(elem);
return selenium.isChecked(elem);
}
protected void selectFile(String uploadElement, String archivePath) {
//Switch to frame
driver.switchTo().frame(driver.findElement(By.tagName("iframe")));
WebDriverWait wait = new WebDriverWait(driver, 5);
// while the following loop runs, the DOM changes -
// page is refreshed, or element is removed and re-added
wait.until(presenceOfElementLocated(By.id(uploadElement)));
//Select the file path for upload.
driver.findElement(By.id(uploadElement)).sendKeys(archivePath);
}
protected boolean isAlertPresent() {
return selenium.isAlertPresent();
}
protected boolean isConfirmationPresent() {
return selenium.isConfirmationPresent();
}
protected String getAlertText() {
return selenium.getAlert();
}
protected void chooseOkOnNextConfirmation() {
selenium.chooseOkOnNextConfirmation();
}
protected String getConfirmation() {
String confirmation = null;
if (isConfirmationPresent()) {
confirmation = selenium.getConfirmation();
}
return confirmation;
}
protected void waitForPopUp(String windowId, String timeout) {
selenium.waitForPopUp(windowId, timeout);
}
protected void selectWindow(String windowId) {
selenium.selectWindow(windowId);
}
protected String getSelectedLabel(String elem) {
waitForElement(elem);
return selenium.getSelectedLabel(elem);
}
protected void open(String url) {
selenium.open(url);
}
protected void submitForm(String formId) {
selenium.submit(formId);
}
// *************************************************************************
// Wrappers for Selenium API
// *************************************************************************
protected String generateRandomString() {
SecureRandom random = new SecureRandom();
// prepend a letter to insure valid JSF ID, which is causing failures in some areas
return "a" + new BigInteger(130, random).toString(16);
}
protected int generateRandomNumber() {
Random r = new Random();
return Math.abs(r.nextInt()) + 1;
}
protected int generateRandomNumber(int max) {
Random r = new Random();
return Math.abs(r.nextInt(max - 1)) + 1;
}
protected <T> T selectRandomItem(T... items) {
Random r = new Random();
return items[r.nextInt(items.length)];
}
protected int getTableRowCount(String id) {
String text = getText(id);
int count = Integer.parseInt(text.substring(text.indexOf("(") + 1, text.indexOf(")")));
return count;
}
protected void openAndWait(String url, String triggerText) {
openAndWait(url, triggerText, TIMEOUT);
}
public void openAndWait(String url, String triggerText, int timeout) {
open(url);
// wait for 2 minutes, as that should be enough time to insure that the admin console app has been deployed by the server
waitForPageLoad(triggerText, timeout);
}
/**
* Click the specified element and wait for the specified trigger text on the resulting page, timing out TIMEOUT seconds.
*
* @param triggerText
*/
protected void clickAndWait(String id, String triggerText) {
clickAndWait(id, triggerText, TIMEOUT);
}
protected void clickAndWait(String id, String triggerText, int seconds) {
log ("Clicking on {0} \"{1}\"", id, triggerText);
waitForElement(id);
insureElementIsVisible(id);
pressButton(id);
waitForPageLoad(triggerText, seconds);
}
protected void clickAndWait(String id, WaitForLoadCallBack callback) {
waitForElement(id);
insureElementIsVisible(id);
pressButton(id);
waitForLoad(TIMEOUT, callback);
}
protected void clickAndWaitForElement(String clickId, final String elementId) {
pressButton(clickId);
waitForLoad(60, new WaitForLoadCallBack() {
@Override
public boolean executeTest() {
if (isElementPresent(elementId)) {
return true;
}
return false;
}
});
}
protected void clickAndWaitForButtonEnabled(String id) {
pressButton(id);
waitForButtonEnabled(id);
}
protected void clickLink(String linkText) {
driver.findElement(By.linkText(linkText)).click();
}
protected void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
}
/**
* Cause the test to wait for the page to load. This will be used, for example, after an initial page load
* (selenium.open) or after an Ajaxy navigation request has been made.
*
* @param triggerText The text that should appear on the page when it has finished loading
* @param timeout How long to wait (in seconds)
*/
protected void waitForPageLoad(String triggerText, int timeout) {
waitForLoad(timeout, new PageLoadCallBack(triggerText, false));
}
protected void waitForPageLoad(final String triggerText, final boolean textShouldBeMissing) {
waitForPageLoad(triggerText, TIMEOUT, textShouldBeMissing);
}
protected void waitForPageLoad(final String triggerText, final int timeout, final boolean textShouldBeMissing) {
waitForLoad(timeout, new PageLoadCallBack(triggerText, textShouldBeMissing));
}
protected void waitForLoad(int timeoutInSeconds, WaitForLoadCallBack callback) {
for (int seconds = 0;; seconds++) {
if (seconds >= (timeoutInSeconds)) {
Assert.fail("The operation timed out waiting for the page to load.");
}
WebElement ajaxPanel = (WebElement) elementFinder.findElement(By.id(AJAX_INDICATOR), TIMEOUT,
new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
try {
WebElement ajaxPanel = (WebElement) driver.findElement(By.id(AJAX_INDICATOR));
return !ajaxPanel.isDisplayed();
} catch (Exception e) {
return false;
}
}
});
// if (!ajaxPanel.isDisplayed()) {
if (callback.executeTest()) {
break;
}
// }
sleep(TIMEOUT_CALLBACK_LOOP);
}
}
// The login page doesn't have the ajax indicator, so we must treat it differently
protected void waitForLoginPageLoad(int timeoutInSeconds) {
for (int seconds = 0;; seconds++) {
if (seconds >= (30)) {
Assert.fail("The operation timed out waiting for the login page to load.");
}
boolean loginFormIsDisplayed = false;
try {
loginFormIsDisplayed = isElementPresent("j_username") || isElementPresent("Login.username");
} catch (Exception ex) {
}
if (loginFormIsDisplayed) {
break;
}
sleep(TIMEOUT_CALLBACK_LOOP);
}
}
protected void handleLogin() {
handleLogin("admin", "", TRIGGER_COMMON_TASKS);
}
protected void handleLogin(String userName, String password, String triggerText) {
processingLogin = true;
setFieldValue("Login.username", userName);
setFieldValue("Login.password", password);
clickAndWait("loginButton", triggerText);
processingLogin = false;
}
protected void waitForButtonEnabled(String buttonId) {
// waitForCondition("document.getElementById('" + buttonId + "').disabled == false", BUTTON_TIMEOUT);
waitForLoad(BUTTON_TIMEOUT, new ButtonDisabledStateCallBack(buttonId, false));
}
protected void waitForButtonDisabled(String buttonId) {
String value = selenium.getEval(CURRENT_WINDOW + ".document.getElementById('" + buttonId + "').disabled");
// waitForCondition("document.getElementById('" + buttonId + "').disabled == true", BUTTON_TIMEOUT);
waitForLoad(BUTTON_TIMEOUT, new ButtonDisabledStateCallBack(buttonId, true));
}
protected void waitForCondition(String js, int timeOutInMillis) {
selenium.waitForCondition(CURRENT_WINDOW + "." + js, Integer.toString(timeOutInMillis));
}
protected void deleteRow(String buttonId, String tableId, String triggerText) {
deleteRow(buttonId, tableId, triggerText, "col0", "col1");
}
protected void deleteRow(final String buttonId, final String tableId, final String triggerText, final String selectColId, final String valueColId) {
rowActionWithConfirm(buttonId, tableId, triggerText, selectColId, valueColId);
waitForLoad(TIMEOUT, new DeleteRowCallBack(tableId, triggerText, valueColId));
// waitForPageLoad(triggerText, true);
}
protected void rowActionWithConfirm(String buttonId, String tableId, String triggerText) {
rowActionWithConfirm(buttonId, tableId, triggerText, "col0", "col1");
}
protected void rowActionWithConfirm(String buttonId, String tableId, String triggerText, String selectColId, String valueColId) {
// A defensive getConfirmation()
getConfirmation();
chooseOkOnNextConfirmation();
selectTableRowByValue(tableId, triggerText, selectColId, valueColId);
sleep(500); // argh!
waitForButtonEnabled(buttonId);
pressButton(buttonId);
getConfirmation();
sleep(500); // argh!
waitForButtonDisabled(buttonId);
}
/**
* This method will scan the all ths links for the link with the given text. We can't rely on a link's position
* in the table, as row order may vary (if, for example, a prior test run left data behind). If the link is not
* found, null is returned, so the calling code may need to check the return value prior to use.
*
* @param baseId
* @param value
* @return
*/
protected String getLinkIdByLinkText(final String baseId, final String value) {
final ExceptionSwallowingLoop<String> loop = new ExceptionSwallowingLoop<String>() {
@Override
public String operation() {
WebElement link = elementFinder.findElement(By.linkText(value), TIMEOUT);
return (link == null) ? null : (String) link.getAttribute("id");
}
};
return loop.get();
}
protected boolean isTextPresent(String text) {
return selenium.isTextPresent(resolveTriggerText(text));
}
protected void selectTableRowByValue(String tableId, String value) {
selectTableRowByValue(tableId, value, "col0", "col1");
}
protected void selectTableRowByValue(String tableId, String value, String selectColId, String valueColId) {
List<String> rows = getTableRowsByValue(tableId, value, valueColId);
for (String row : rows) {
// It seems this must be click for the JS to fire in the browser
final String id = row + ":" + selectColId + ":select";
selectTableRow(row, selectColId);
}
}
/**
* @See selectTableRowByValue(String tableId, String value, String selectColId, String valueColId);
* @param baseId
* @param value
* @return
*/
protected int selectTableRowsByValue(String baseId, String value) {
return selectTableRowsByValue(baseId, value, "col0", "col1");
}
/**
* For the given table, this method will select each row whose value in the specified column
* matched the value given, returning the number of rows selected.
*/
protected int selectTableRowsByValue(String tableId, String value, String selectColId, String valueColId) {
List<String> rows = getTableRowsByValue(tableId, value, valueColId);
if (!rows.isEmpty()) {
for (String row : rows) {
selectTableRow(row, selectColId);
}
}
return rows.size();
}
private void selectTableRow(String rowId, String colId) {
boolean rowHighlighted = false;
int iterations = 0;
this.log("Clicking on {0} in row {1} and making it sure it is highlighted", colId, rowId);
while (!rowHighlighted && (iterations <= 50)) {
selenium.click(rowId + ":" + colId + ":select");
markCheckbox(rowId + ":" + colId + ":select");
sleep(500);
String rowClass = selenium.getAttribute("identifier="+rowId+"@class");
rowHighlighted = ((rowClass != null) && (rowClass.contains("TblSelRow_sun4")));
iterations++;
}
if (iterations >= 50) {
Assert.fail("Timed out wait for row in " + rowId + " to be selected");
}
}
protected void deleteAllTableRows(String tableId, int colId) {
String deleteButtonId = tableId + ":topActionsGroup1:button1";
selectAllTableRows(tableId, colId);
waitForButtonEnabled(deleteButtonId);
chooseOkOnNextConfirmation();
pressButton(deleteButtonId);
getConfirmation();
this.waitForButtonDisabled(deleteButtonId);
}
protected void selectAllTableRows(String tableId, int colId) {
int count = getTableRowCount(tableId);
for (int i = 0 ; i < count; i++) {
selenium.click(tableId+":rowGroup1:" + i +":col" + colId + ":select");
markCheckbox(tableId+":rowGroup1:" + i +":col" + colId + ":select");
}
}
// TODO: write javadocs for this
protected String getTableRowByValue(String tableId, String value, String valueColId) {
try {
int row = 0;
while (true) { // iterate over any rows
// Assume one row group for now and hope it doesn't bite us
String text = getText(tableId + ":rowGroup1:" + row + ":" + valueColId);
if (text.equals(value)) {
return tableId + ":rowGroup1:" + row + ":";
}
row++;
}
} catch (Exception e) {
Assert.fail("The specified row was not found: " + value);
return "";
}
}
protected List<String> getTableRowsByValue(String tableId, String value, String valueColId) {
List<String> rows = new ArrayList<String>();
try {
int row = 0;
while (true) { // iterate over any rows
// Assume one row group for now and hope it doesn't bite us
String text = getText(tableId + ":rowGroup1:" + row + ":" + valueColId);
if (text.contains(value)) {
rows.add(tableId + ":rowGroup1:" + row);
}
row++;
}
} catch (Exception e) {
}
return rows;
}
// TODO: write javadocs for this
protected int getTableRowCountByValue(String tableId, String value, String valueColId, Boolean isLabel) {
int tableCount = getTableRowCount(tableId);
int selectedCount = 0;
try {
for (int i = 0; i < tableCount; i++) {
String text = "";
if (isLabel) {
text = getText(tableId + ":rowGroup1:" + i + ":" + valueColId);
} else {
text = getFieldValue(tableId + ":rowGroup1:" + i + ":" + valueColId);
}
if (text.equals(value)) {
selectedCount++;
}
}
} catch (Exception e) {
Assert.fail("The specified row was not found: " + value);
return 0;
}
return selectedCount;
}
protected int getTableRowCountByValue(String tableId, String value, String valueColId) {
return getTableRowCountByValue(tableId, value, valueColId, true);
}
protected List<String> getTableColumnValues(String tableId, String columnId) {
List<String> values = new ArrayList<String>();
int tableCount = getTableRowCount(tableId);
try {
int row = 0;
while (true) { // iterate over any rows
// Assume one row group for now and hope it doesn't bite us
values.add(getText(tableId + ":rowGroup1:" + row + ":" + columnId));
row++;
}
} catch (Exception e) {
}
return values;
}
protected boolean tableContainsRow(String tableId, String columnId, String value) {
return getTableRowCountByValue(tableId, value, columnId) > 0;
}
protected int addTableRow(String tableId, String buttonId) {
return addTableRow(tableId, buttonId, "Additional Properties");
}
protected int addTableRow(String tableId, String buttonId, String countLabel) {
int count = getTableRowCount(tableId);
clickAndWait(buttonId, new AddTableRowCallBack(tableId, count));
return ++count;
}
protected void assertTableRowCount(String tableId, int count) {
Assert.assertEquals(count, getTableRowCount(tableId));
}
protected void waitForTableRowCount(String tableID, int count) {
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(presenceOfElementLocated(By.id(tableID)));
try {
int tableCount = getTableRowCount(tableID);
} catch (Exception e) {
e.printStackTrace();
}
sleep(500);
}
// Look at all those params. Maybe this isn't such a hot idea.
/**
* @param resourceName
* @param tableId
* @param enableButtonId
* @param statusID
* @param backToTableButtonId
* @param tableTriggerText
* @param editTriggerText
*/
protected void testEnableButton(String resourceName,
String tableId,
String enableButtonId,
String statusID,
String backToTableButtonId,
String tableTriggerText,
String editTriggerText,
String statusMsg) {
testEnableDisableButton(resourceName, tableId, enableButtonId, statusID, backToTableButtonId, tableTriggerText, editTriggerText, statusMsg);
}
protected void testDisableButton(String resourceName,
String tableId,
String disableButtonId,
String statusId,
String backToTableButtonId,
String tableTriggerText,
String editTriggerText,
String statusMsg) {
testEnableDisableButton(resourceName, tableId, disableButtonId, statusId, backToTableButtonId, tableTriggerText, editTriggerText, statusMsg);
}
private void testEnableDisableButton(String resourceName,
String tableId,
String enableButtonId,
String statusId,
String backToTableButtonId,
String tableTriggerText,
String editTriggerText,
String state) {
sleep(TIMEOUT_CALLBACK_LOOP); // yuck
selectTableRowByValue(tableId, resourceName);
waitForButtonEnabled(enableButtonId);
pressButton(enableButtonId);
waitForButtonDisabled(enableButtonId);
waitForPageLoad(resourceName, false);
clickAndWait(getLinkIdByLinkText(tableId, resourceName), editTriggerText);
// TODO: this is an ugly, ugly hack and needs to be cleaned up
if(state.contains("Target")) {
Assert.assertEquals(state, getText(statusId));
} else {
if ("on".equals(state) || "off".equals(state)) {
Assert.assertEquals("on".equals(state), isChecked(statusId));
} else {
Assert.assertEquals(state, getFieldValue(statusId));
}
}
clickAndWait(backToTableButtonId, tableTriggerText);
}
protected void testEnableOrDisableTarget(String tableSelectMutlipleId,
String enableButtonId,
String generalTabId,
String targetTabId,
String statusId,
String generalTriggerText,
String targetTriggerText,
String state) {
pressButton(tableSelectMutlipleId);
waitForButtonEnabled(enableButtonId);
pressButton(enableButtonId);
waitForButtonDisabled(enableButtonId);
clickAndWait(generalTabId, generalTriggerText);
Assert.assertEquals(state, getText(statusId));
clickAndWait(targetTabId, targetTriggerText);
}
protected void testManageTargets(String resourcesLinkId,
String resourcesTableId,
String enableButtonId,
String disableButtonId,
String enableOrDisableTextFieldId,
String resGeneralTabId,
String resTargetTabId,
String resourcesTriggerText,
String resEditTriggerText,
String jndiName,
String instanceName) {
final String TRIGGER_EDIT_RESOURCE_TARGETS = "Resource Targets";
final String enableStatus = "Enabled on 2 of 2 Target(s)";
final String disableStatus = "Enabled on 0 of 2 Target(s)";
final String TRIGGER_MANAGE_TARGETS = "Manage Resource Targets";
final String DEFAULT_SERVER = "server";
reset();
clickAndWait(resourcesLinkId, resourcesTriggerText);
waitForPageLoad(jndiName, false);
clickAndWait(getLinkIdByLinkText(resourcesTableId, jndiName), resEditTriggerText);
//Click on the target tab and verify whether the target is in the target table or not.
clickAndWait(resTargetTabId, TRIGGER_EDIT_RESOURCE_TARGETS);
Assert.assertTrue(isTextPresent(instanceName));
//Disable all targets
testEnableOrDisableTarget("propertyForm:targetTable:_tableActionsTop:_selectMultipleButton:_selectMultipleButton_image",
disableButtonId,
resGeneralTabId,
resTargetTabId,
enableOrDisableTextFieldId,
resEditTriggerText,
TRIGGER_EDIT_RESOURCE_TARGETS,
disableStatus);
//Enable all targets
testEnableOrDisableTarget("propertyForm:targetTable:_tableActionsTop:_selectMultipleButton:_selectMultipleButton_image",
enableButtonId,
resGeneralTabId,
resTargetTabId,
enableOrDisableTextFieldId,
resEditTriggerText,
TRIGGER_EDIT_RESOURCE_TARGETS,
enableStatus);
//Test the manage targets : Remove the server from targets.
clickAndWait("propertyForm:targetTable:topActionsGroup1:manageTargetButton", TRIGGER_MANAGE_TARGETS);
addSelectSelection("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_selected", DEFAULT_SERVER);
pressButton("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_removeButton");
clickAndWait("form:propertyContentPage:topButtons:saveButton", TRIGGER_NEW_VALUES_SAVED);
//Test the issue : 13280
//If server instance is not one of the target, edit resource was failing. Fixed that and added a test
clickAndWait(resourcesLinkId, resourcesTriggerText);
waitForPageLoad(jndiName, false);
clickAndWait(getLinkIdByLinkText(resourcesTableId, jndiName), resEditTriggerText);
Assert.assertTrue(isTextPresent(jndiName));
clickAndWait(resTargetTabId, TRIGGER_EDIT_RESOURCE_TARGETS);
//Test the manage targets : Remove the instance and add the server.
clickAndWait("propertyForm:targetTable:topActionsGroup1:manageTargetButton", TRIGGER_MANAGE_TARGETS);
addSelectSelection("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_selected", instanceName);
waitForButtonEnabled("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_removeButton");
pressButton("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_removeButton");
waitForButtonDisabled("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_removeButton");
selenium.removeAllSelections("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_available");
addSelectSelection("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove_available", DEFAULT_SERVER);
waitForButtonEnabled("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_addButton");
pressButton("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_addButton");
waitForButtonDisabled("form:targetSection:targetSectionId:addRemoveProp:commonAddRemove:commonAddRemove_addButton");
clickAndWait("form:propertyContentPage:topButtons:saveButton", TRIGGER_NEW_VALUES_SAVED);
waitForPageLoad(instanceName, false);
Assert.assertTrue(isTextPresent(DEFAULT_SERVER));
//Go Back to Resources Page
clickAndWait(resourcesLinkId, resourcesTriggerText);
}
protected void logDebugMessage(String message) {
if (DEBUG) {
logger.info(message);
}
}
protected String resolveTriggerText(String original) {
String triggerText = original;
int index = original.indexOf(".");
if (index > -1) {
String bundleName = original.substring(0, index);
String key = original.substring(index + 1);
String bundle = bundles.get(bundleName);
if (bundle != null) {
ResourceBundle res = ResourceBundle.getBundle(bundle);
if (res != null) {
// Strip out HTML. Hopefully this will be robust enough
triggerText = res.getString(key).replaceAll("<.*?>", "");
} else {
Logger.getLogger(BaseSeleniumTestClass.class.getName()).log(Level.WARNING, null, "An invalid resource bundle was specified: " + original);
}
}
}
return triggerText;
}
protected void log(String message, String... args) {
if (DEBUG) {
String[] temp = new String[args.length];
for (int i = 0; i < args.length; i++) {
temp[i] = resolveTriggerText(args[i]);
}
logger.log(Level.INFO, message, temp);
}
}
private void waitForElement(String elem) {
// times out after 5 seconds
WebDriverWait wait = new WebDriverWait(driver, 5);
// while the following loop runs, the DOM changes -
// page is refreshed, or element is removed and re-added
wait.until(presenceOfElementLocated(By.id(elem)));
selenium.focus(elem);
}
private static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
return new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
private void insureElementIsVisible (final String id) {
if (!id.contains("treeForm:tree")) {
return;
}
try {
WebElement element = (WebElement) elementFinder.findElement(By.id(id), TIMEOUT);
//driver.findElement(By.id(id));
if (element.isDisplayed()) {
return;
}
} catch (StaleElementReferenceException sere) {
}
final String parentId = id.substring(0, id.lastIndexOf(":"));
final WebElement parentElement = (WebElement) elementFinder.findElement(By.id(parentId), TIMEOUT);
// driver.findElement(By.id(parentId));
if (!parentElement.isDisplayed()) {
insureElementIsVisible(parentId);
String grandParentId = parentId.substring(0, parentId.lastIndexOf(":"));
String nodeId = grandParentId.substring(grandParentId.lastIndexOf(":") + 1);
pressButton(grandParentId + ":" + nodeId + "_turner");
}
}
class PageLoadCallBack implements WaitForLoadCallBack {
boolean textShouldBeMissing;
String triggerText;
public PageLoadCallBack(String triggerText, boolean textShouldBeMissing) {
this.textShouldBeMissing = textShouldBeMissing;
this.triggerText = resolveTriggerText(triggerText);
}
@Override
public boolean executeTest() {
boolean found = false;
try {
if (isElementPresent("j_username") && !processingLogin) {
handleLogin();
}
if (!textShouldBeMissing) {
boolean visible = false;
final List<WebElement> elements = driver.findElements(By.xpath("//*[contains(text(), \"" +
triggerText.replace("\"", "\\\"") + "\")]"));
if (!elements.isEmpty()) {
for (WebElement e : elements) {
if (e.isDisplayed()) {
visible = true;
}
}
} else {
visible = true;
}
if (isTextPresent(triggerText) && visible) {
found = true;
}
} else if (!isTextPresent(triggerText)) {
found = true;
} else {
if (isTextPresent("RuntimeException")) {
Assert.fail("Exception detected on page. Please check the logs for details");
}
}
} catch (SeleniumException se) {
String message = se.getMessage();
if (!"ERROR: Couldn't access document.body. Is this HTML page fully loaded?".equals(message)) {
Assert.fail(message);
}
}
return found;
}
};
class DeleteRowCallBack implements WaitForLoadCallBack {
private String tableId;
private String tableRowValue;
private String tableColId;
public DeleteRowCallBack(String tableId, String tableRowValue, String tableColId) {
this.tableId = tableId;
this.tableRowValue = tableRowValue;
this.tableColId = tableColId;
}
@Override
public boolean executeTest() {
try {
List<String> rows = getTableRowsByValue(tableId, tableRowValue, tableColId);
return rows.isEmpty();
} catch (SeleniumException se) {
return false;
}
}
}
class AddTableRowCallBack implements WaitForLoadCallBack {
private final String tableId;
private final int initialCount;
public AddTableRowCallBack(String tableId, int initialCount) {
this.tableId = tableId;
this.initialCount = initialCount;
}
@Override
public boolean executeTest() {
try {
int count = getTableRowCount(tableId);
return count > initialCount;
} catch (Exception e) {
return false;
}
}
};
class ButtonDisabledStateCallBack implements WaitForLoadCallBack {
private String buttonId;
private boolean desiredState;
public ButtonDisabledStateCallBack(String buttonId, boolean desiredState) {
this.buttonId = buttonId;
this.desiredState = desiredState;
}
@Override
public boolean executeTest() {
// String attr = selenium.getEval("this.browserbot.findElement('id=" + buttonId + "').disabled"); // "Classic" Selenium
try {
String attr =
elementFinder.findElement(By.id(buttonId), TIMEOUT) // driver.findElement(By.id(buttonId))
.getAttribute("disabled"); // WebDriver-backed Selenium
return (Boolean.parseBoolean(attr) == desiredState);
} catch (Exception ex) {
return true;// ???
}
}
}
abstract class ExceptionSwallowingLoop<T> {
public T get() {
T value = null;
boolean success = false;
int count = 0;
while (!success && (count < TIMEOUT /2 )) {
try {
value = operation();
success = true;
} catch (Exception e) {
logger.log(Level.FINE, "Exception caught ('{0}'). Sleeping...", e.getMessage());
count++;
}
}
return value;
}
public abstract T operation();
}
}