org.beangle.test.selenium.SeleniumTestBase.java Source code

Java tutorial

Introduction

Here is the source code for org.beangle.test.selenium.SeleniumTestBase.java

Source

/*
 * Beangle, Agile Java/Scala Development Scaffold and Toolkit
 *
 * Copyright (c) 2005-2013, Beangle Software.
 *
 * Beangle is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Beangle is distributed in the hope that it will be useful.
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Beangle.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.beangle.test.selenium;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;

/**
 * EMS  Selenium? com.thoughtworks.selenium.SeleneseTestBase
 * 
 * @author qianjia
 */
public class SeleniumTestBase extends SeleniumTestBootstrap {

    protected StringBuffer verificationErrors = new StringBuffer();

    protected static final String CHECKBOX_PATTERN = "xpath=//input[@type=''checkbox'' and @name=''{0}'']";

    protected static final String SINGLE_RADIO_PATTERN = "xpath=(//input[(@type=''radio'') and @name=''{0}''])[{1}]";
    protected static final String SINGLE_CHECKBOX_PATTERN = "xpath=(//input[(@type=''checkbox'') and @name=''{0}''])[{1}]";
    protected static final String SINGLE_CHECKBOX_RADIO_PATTERN = "xpath=(//input[(@type=''checkbox'' or @type=''radio'') and @name=''{0}''])[{1}]";
    protected static final String JQUERY_TAB_PATTERN = "css=.ui-tabs-nav a[title=''{0}'']";

    protected static final double ELEMENT_TIMEOUT_SEC_LONG = 20;
    protected static final double ELEMENT_TIMEOUT_SEC_SHORT = 1;

    @AfterTest(alwaysRun = true)
    public void tearDown() throws Exception {
        checkForVerificationErrors();
    }

    @BeforeMethod(dependsOnGroups = "webdriver.start")
    public void setTestContext(Method method) {
        selenium.setContext(method.getDeclaringClass().getSimpleName() + "." + method.getName());
    }

    /**
     * Asserts that there were no verification errors during the current test, failing immediately
     * if
     * any are found
     */
    @AfterMethod
    public void checkForVerificationErrors() {
        String verificationErrorString = verificationErrors.toString();
        clearVerificationErrors();
        if (!"".equals(verificationErrorString)) {
            fail(verificationErrorString);
        }
    }

    /** Like assertTrue, but fails at the end of the test (during tearDown) */
    public void verifyTrue(boolean b) {
        try {
            assertTrue(b);
        } catch (Error e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Like assertFalse, but fails at the end of the test (during tearDown) */
    public void verifyFalse(boolean b) {
        try {
            assertFalse(b);
        } catch (Error e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Returns the body text of the current page */
    public String getText() {
        return selenium.getEval("this.page().bodyText()");
    }

    /** Like assertEquals, but fails at the end of the test (during tearDown) */
    public void verifyEquals(Object expected, Object actual) {
        try {
            assertEquals(expected, actual);
        } catch (Error e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Like assertEquals, but fails at the end of the test (during tearDown) */
    public void verifyEquals(boolean expected, boolean actual) {
        try {
            assertEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
        } catch (Error e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Like JUnit's Assert.assertEquals, but knows how to compare string arrays */
    public static void assertEquals(Object expected, Object actual) {
        if (expected == null) {
            assertTrue("Expected \"" + expected + "\" but saw \"" + actual + "\" instead", actual == null);
        } else if (expected instanceof String && actual instanceof String) {
            assertEquals((String) expected, (String) actual);
        } else if (expected instanceof String && actual instanceof String[]) {
            assertEquals((String) expected, (String[]) actual);
        } else if (expected instanceof String && actual instanceof Number) {
            assertEquals((String) expected, actual.toString());
        } else if (expected instanceof Number && actual instanceof String) {
            assertEquals(expected.toString(), (String) actual);
        } else if (expected instanceof String[] && actual instanceof String[]) {
            assertEquals((String[]) expected, (String[]) actual);
        } else {
            assertTrue("Expected \"" + expected + "\" but saw \"" + actual + "\" instead", expected.equals(actual));
        }
    }

    /** Like JUnit's Assert.assertEquals, but handles "regexp:" strings like HTML Selenese */
    public static void assertEquals(String expected, String actual) {
        assertTrue("Expected \"" + expected + "\" but saw \"" + actual + "\" instead",
                seleniumEquals(expected, actual));
    }

    /**
     * Like JUnit's Assert.assertEquals, but joins the string array with commas, and handles
     * "regexp:"
     * strings like HTML Selenese
     */
    public static void assertEquals(String expected, String[] actual) {
        assertEquals(expected, join(actual, ','));
    }

    /**
     * Compares two strings, but handles "regexp:" strings like HTML Selenese
     * 
     * @param expectedPattern
     * @param actual
     * @return true if actual matches the expectedPattern, or false otherwise
     */
    public static boolean seleniumEquals(String expectedPattern, String actual) {
        if (expectedPattern == null || actual == null) {
            return expectedPattern == null && actual == null;
        }
        if (actual.startsWith("regexp:") || actual.startsWith("regex:") || actual.startsWith("regexpi:")
                || actual.startsWith("regexi:")) {
            // swap 'em
            String tmp = actual;
            actual = expectedPattern;
            expectedPattern = tmp;
        }
        Boolean b;
        b = handleRegex("regexp:", expectedPattern, actual, 0);
        if (b != null) {
            return b.booleanValue();
        }
        b = handleRegex("regex:", expectedPattern, actual, 0);
        if (b != null) {
            return b.booleanValue();
        }
        b = handleRegex("regexpi:", expectedPattern, actual, Pattern.CASE_INSENSITIVE);
        if (b != null) {
            return b.booleanValue();
        }
        b = handleRegex("regexi:", expectedPattern, actual, Pattern.CASE_INSENSITIVE);
        if (b != null) {
            return b.booleanValue();
        }

        if (expectedPattern.startsWith("exact:")) {
            String expectedExact = expectedPattern.replaceFirst("exact:", "");
            if (!expectedExact.equals(actual)) {
                System.out.println("expected " + actual + " to match " + expectedPattern);
                return false;
            }
            return true;
        }

        String expectedGlob = expectedPattern.replaceFirst("glob:", "");
        expectedGlob = expectedGlob.replaceAll("([\\]\\[\\\\{\\}$\\(\\)\\|\\^\\+.])", "\\\\$1");

        expectedGlob = expectedGlob.replaceAll("\\*", ".*");
        expectedGlob = expectedGlob.replaceAll("\\?", ".");
        if (!Pattern.compile(expectedGlob, Pattern.DOTALL).matcher(actual).matches()) {
            System.out.println("expected \"" + actual + "\" to match glob \"" + expectedPattern
                    + "\" (had transformed the glob into regexp \"" + expectedGlob + "\"");
            return false;
        }
        return true;
    }

    private static Boolean handleRegex(String prefix, String expectedPattern, String actual, int flags) {
        if (expectedPattern.startsWith(prefix)) {
            String expectedRegEx = expectedPattern.replaceFirst(prefix, ".*") + ".*";
            Pattern p = Pattern.compile(expectedRegEx, flags);
            if (!p.matcher(actual).matches()) {
                System.out.println("expected " + actual + " to match regexp " + expectedPattern);
                return Boolean.FALSE;
            }
            return Boolean.TRUE;
        }
        return null;
    }

    /**
     * Compares two objects, but handles "regexp:" strings like HTML Selenese
     * 
     * @see #seleniumEquals(String, String)
     * @return true if actual matches the expectedPattern, or false otherwise
     */
    public static boolean seleniumEquals(Object expected, Object actual) {
        if (expected == null) {
            return actual == null;
        }
        if (expected instanceof String && actual instanceof String) {
            return seleniumEquals((String) expected, (String) actual);
        }
        return expected.equals(actual);
    }

    /** Asserts that two string arrays have identical string contents */
    public static void assertEquals(String[] expected, String[] actual) {
        String comparisonDumpIfNotEqual = verifyEqualsAndReturnComparisonDumpIfNot(expected, actual);
        if (comparisonDumpIfNotEqual != null) {
            throw new AssertionError(comparisonDumpIfNotEqual);
        }
    }

    /**
     * Asserts that two string arrays have identical string contents (fails at the end of the test,
     * during tearDown)
     */
    public void verifyEquals(String[] expected, String[] actual) {
        String comparisonDumpIfNotEqual = verifyEqualsAndReturnComparisonDumpIfNot(expected, actual);
        if (comparisonDumpIfNotEqual != null) {
            verificationErrors.append(comparisonDumpIfNotEqual);
        }
    }

    private static String verifyEqualsAndReturnComparisonDumpIfNot(String[] expected, String[] actual) {
        boolean misMatch = false;
        if (expected.length != actual.length) {
            misMatch = true;
        }
        for (int j = 0; j < expected.length; j++) {
            if (!seleniumEquals(expected[j], actual[j])) {
                misMatch = true;
                break;
            }
        }
        if (misMatch) {
            return "Expected " + stringArrayToString(expected) + " but saw " + stringArrayToString(actual);
        }
        return null;
    }

    private static String stringArrayToString(String[] sa) {
        StringBuffer sb = new StringBuffer("{");
        for (int j = 0; j < sa.length; j++) {
            sb.append(" ").append("\"").append(sa[j]).append("\"");
        }
        sb.append(" }");
        return sb.toString();
    }

    private static String throwableToString(Throwable t) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        t.printStackTrace(pw);
        return sw.toString();
    }

    public static String join(String[] sa, char c) {
        StringBuffer sb = new StringBuffer();
        for (int j = 0; j < sa.length; j++) {
            sb.append(sa[j]);
            if (j < sa.length - 1) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /** Like assertNotEquals, but fails at the end of the test (during tearDown) */
    public void verifyNotEquals(Object expected, Object actual) {
        try {
            assertNotEquals(expected, actual);
        } catch (AssertionError e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Like assertNotEquals, but fails at the end of the test (during tearDown) */
    public void verifyNotEquals(boolean expected, boolean actual) {
        try {
            assertNotEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
        } catch (AssertionError e) {
            verificationErrors.append(throwableToString(e));
        }
    }

    /** Asserts that two objects are not the same (compares using .equals()) */
    public static void assertNotEquals(Object expected, Object actual) {
        if (expected == null) {
            assertFalse("did not expect null to be null", actual == null);
        } else if (expected.equals(actual)) {
            fail("did not expect (" + actual + ") to be equal to (" + expected + ")");
        }
    }

    public static void fail(String message) {
        throw new AssertionError(message);
    }

    static public void assertTrue(String message, boolean condition) {
        if (!condition)
            fail(message);
    }

    static public void assertTrue(boolean condition) {
        assertTrue(null, condition);
    }

    static public void assertFalse(String message, boolean condition) {
        assertTrue(message, !condition);
    }

    static public void assertFalse(boolean condition) {
        assertTrue(null, !condition);
    }

    /** Asserts that two booleans are not the same */
    public static void assertNotEquals(boolean expected, boolean actual) {
        assertNotEquals(Boolean.valueOf(expected), Boolean.valueOf(actual));
    }

    /** Sleeps for the specified number of milliseconds */
    public void pause(int millisecs) {
        try {
            Thread.sleep(millisecs);
        } catch (InterruptedException e) {
        }
    }

    /** Clears out the list of verification errors */
    public void clearVerificationErrors() {
        verificationErrors = new StringBuffer();
    }

    @AfterMethod(alwaysRun = true)
    public void selectDefaultWindow() {
        if (selenium != null) {
            selenium.selectWindow("null");
        }
    }

    /**
     * ?ELEMENT_TIMEOUT_SEC_LONG
     * 
     * @param locator
     * @throws Exception
     */
    protected void waitForElementPresent(String locator) throws Exception {
        waitForElementPresent(locator, ELEMENT_TIMEOUT_SEC_LONG);
    }

    /**
     * ?DOM??
     * 
     * @param locator
     * @param timeoutSecs
     * @throws Exception
     */
    protected void waitForElementPresent(String locator, double timeoutSecs) throws Exception {
        int lap = 300;

        for (int milliseconds = 0;; milliseconds += lap) {
            if (milliseconds >= timeoutSecs * 1000)
                fail("timeout: " + locator);
            try {
                if (selenium.isElementPresent(locator) && selenium.isVisible(locator)) {
                    break;
                }
            } catch (Exception e) {
            }
            Thread.sleep(lap);
        }
    }

    /**
     * ??DOM???ELEMENT_TIMEOUT_SEC_LONG
     * 
     * @param locator
     * @throws Exception
     */
    protected void waitForElementVanish(String locator) throws Exception {
        int lap = 300;
        double timeoutSecs = ELEMENT_TIMEOUT_SEC_LONG;

        for (int milliseconds = 0;; milliseconds += lap) {
            if (milliseconds >= timeoutSecs * 1000)
                fail("timeout: " + locator);
            try {
                if (!selenium.isElementPresent(locator) || !selenium.isVisible(locator))
                    break;
            } catch (Exception e) {
            }
            Thread.sleep(lap);
        }
    }

    /**
     * ??DOM???
     * 
     * @param locator
     * @param timeoutSecs
     * @throws Exception
     */
    protected void waitForElementVanish(String locator, double timeoutSecs) throws Exception {
        int lap = 300;

        for (int milliseconds = 0;; milliseconds += lap) {
            if (milliseconds >= timeoutSecs * 1000)
                fail("timeout: " + locator);
            try {
                if (!selenium.isElementPresent(locator) || !selenium.isVisible(locator))
                    break;
            } catch (Exception e) {
            }
            Thread.sleep(lap);
        }
    }

    /**
     * jQuery-ui?Tab
     * 
     * @param text
     * @throws Exception
     */
    protected void clickJQueryTab(String text) throws Exception {
        String locator = MessageFormat.format(JQUERY_TAB_PATTERN, text);
        waitForElementPresent(locator);

        selenium.click(locator);
        selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
    }

    /**
     * color box
     * @throws Exception 
     */
    protected void closeColorbox() throws Exception {
        String locator = "css=div#cboxClose";
        waitForElementPresent(locator, ELEMENT_TIMEOUT_SEC_SHORT);

        selenium.click(locator);
        waitForElementVanish("css=#cboxLoadedContent");
    }

    /**
     * check?checkbox/radio
     * 
     * @param name
     * @param index
     *            1
     * @throws Exception
     */
    protected void check(String name, int index) throws Exception {
        String locator = MessageFormat.format(SINGLE_CHECKBOX_RADIO_PATTERN, name, index);
        waitForElementPresent(locator);

        if (!selenium.isChecked(locator)) {
            selenium.click(locator);
        }
    }

    /**
     * ???checkbox/radio
     * 
     * @throws Exception
     */
    protected void uncheck(String name, int index) throws Exception {
        String locator = MessageFormat.format(SINGLE_CHECKBOX_RADIO_PATTERN, name, index);
        waitForElementPresent(locator);

        if (selenium.isChecked(locator)) {
            selenium.click(locator);
        }
    }

    /**
     * ?checkbox
     * @param name
     * @throws Exception 
     */
    protected void checkAll(String name) throws Exception {
        int count = selenium.getXpathCount(MessageFormat.format(CHECKBOX_PATTERN.replace("xpath=", ""), name))
                .intValue();
        for (int i = 1; i <= count; i++) {
            String single_box_locator = MessageFormat.format(SINGLE_CHECKBOX_PATTERN, name, i);
            if (!selenium.isChecked(single_box_locator)) {
                selenium.click(single_box_locator);
            }
        }
    }

    /**
     * ??checkbox
     * @param name
     */
    protected void uncheckAll(String name) {
        int count = selenium.getXpathCount(MessageFormat.format(CHECKBOX_PATTERN.replace("xpath=", ""), name))
                .intValue();
        for (int i = 1; i <= count; i++) {
            String single_box_locator = MessageFormat.format(SINGLE_CHECKBOX_PATTERN, name, i);
            if (selenium.isChecked(single_box_locator)) {
                selenium.click(single_box_locator);
            }
        }
    }

    /**
     * list?checkbox?
     * 
     * @param name
     * @return
     * @throws Exception
     */
    protected boolean isChecked(String name, int index) throws Exception {
        String locator = MessageFormat.format(SINGLE_CHECKBOX_RADIO_PATTERN, name, index);
        return selenium.isChecked(locator);
    }

    /**
     * ??Form??Form??
     * 
     * @throws Exception
     */
    protected void submitForm() throws Exception {
        submitForm(null);
    }

    /**
     * ??Form
     * 
     * @param formName
     * @throws Exception
     */
    protected void submitForm(String formName) throws Exception {
        // TODO HTML5 compatible
        String locator = "css=input[type=submit]";
        if (StringUtils.isNotBlank(formName)) {
            locator = "css=form[name=" + formName + "] input[type=submit]";
        }
        selenium.click(locator);
        selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
    }

    /**
     * ?Form??Form??
     * @throws Exception
     */
    protected void resetForm() throws Exception {
        resetForm(null);
    }

    /**
     * ?Form
     * @param formName
     * @throws Exception
     */
    protected void resetForm(String formName) throws Exception {
        String locator = "css=input[type=reset]";
        if (StringUtils.isNotBlank(formName)) {
            locator = "css=form[name=" + formName + "] input[type=reset]";
        }
        selenium.click(locator);
    }

    /**
     * select?option
     */
    protected void select(String selectName, String optionText) {
        String selectLocator = "css=select[name='" + selectName + "']";
        String optionLocator = "label=" + optionText;
        selenium.select(selectLocator, optionLocator);
        selenium.waitForPageToLoad(PAGE_LOAD_TIMEOUT);
    }

}