/** * Candybean is a next generation automation and testing framework suite. * It is a collection of components that foster test automation, execution * configuration, data abstraction, results illustration, tag-based execution, * top-down and bottom-up batches, mobile variants, test translation across * languages, plain-language testing, and web service testing. * Copyright (C) 2013 SugarCRM, Inc. <candybean@sugarcrm.com> * <p> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * <p> * This program 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 Affero General Public License for more details. * <p> * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.sugarcrm.candybean.automation.webdriver; import com.sugarcrm.candybean.automation.AutomationInterface.Type; import com.sugarcrm.candybean.automation.AutomationInterfaceBuilder; import com.sugarcrm.candybean.automation.Candybean; import com.sugarcrm.candybean.automation.element.Hook; import com.sugarcrm.candybean.automation.element.Hook.Strategy; import com.sugarcrm.candybean.configuration.Configuration; import com.sugarcrm.candybean.exceptions.CandybeanException; import com.sugarcrm.candybean.testUtilities.TestConfiguration; import org.junit.*; import org.junit.rules.ExpectedException; import java.util.List; import java.util.concurrent.TimeUnit; /** * Tests for WebDriverElement.class * * Tests use the local web pages in resources/html/test/ to avoid needing an internet * connection to test. The html page testPlayground.html contains a variety of elements * each contained within a div. * * When selecting elements, the general rule of thumb is to include the id of the parent * div if it is relevant. For example, if you wanted the span with id "writingSpan" * because you wanted to test element visibility, you would search for it with * $("#clickToHideDiv #writingSpan") * However, if you only wanted it because you needed a span element to test against, you * would not list the parent's div name because the ability to click to hide is irrelevant, * search for it using: * $("#writingSpan") * * There's no 100% answer when to use either, so use what you feel best portrays your intent */ public class WebDriverElementSystemTest { private WebDriverInterface iface; final String testPage = "file://" + System.getProperty("user.dir") + "/resources/html/test/testPlayground.html"; // Creating this function privately for now, a full implementation in WebDriverElement // is detailed in CB-265 private WebDriverElement $(String cssPath) throws CandybeanException { return iface.getWebDriverElement(Strategy.CSS, cssPath); } @Before public void setUp() throws Exception { Configuration config = TestConfiguration.getTestConfiguration("systemtest.webdriver.config"); Candybean candybean = Candybean.getInstance(config); AutomationInterfaceBuilder builder = candybean.getAIB(WebDriverElementSystemTest.class); builder.setType(Type.CHROME); iface = builder.build(); iface.start(); } @After public void tearDown() throws CandybeanException { iface.stop(); } @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void getAttributeTest() throws Exception { iface.go(testPage); WebDriverElement element = $("#toggleWritingButton"); Assert.assertEquals("button", element.getAttribute("type")); } @Test public void getElementTest() throws Exception { iface.go(testPage); WebDriverElement div = $("#clickToHideDiv"); final WebDriverElement elementByTag = ((WebDriverElement) div.getElement( new Hook(Strategy.TAG, "span"), 0)); Assert.assertEquals("Click button to hide me", elementByTag.getText()); final WebDriverElement elementById = (WebDriverElement) div.getElement( new Hook(Strategy.ID, "writingSpan"), 0); Assert.assertEquals("Click button to hide me", elementById.getText()); final WebDriverElement elementByClass = (WebDriverElement) div.getElement( new Hook(Strategy.CLASS, "onScreen"), 0); Assert.assertEquals("Click to hide writing", elementByClass.getText()); final WebDriverElement elementByXPath= (WebDriverElement) div.getElement( new Hook(Strategy.XPATH, "//*[@id=\"writingSpan\"]"), 0); Assert.assertEquals("Click button to hide me", elementByXPath.getText()); WebDriverElement namesDiv = $("#sameNamedElementsDiv"); for (int i = 0; i < 4; i ++) { WebDriverElement elementByName = (WebDriverElement) namesDiv.getElement( new Hook(Strategy.NAME, "namedInput"), i); Assert.assertEquals("This is named input "+ i, elementByName.getText()); } } @Test public void getElementsTest() throws Exception { iface.go(testPage); List<WebDriverElement> elements = iface.getWebDriverElements(Strategy.NAME, "namedInput"); Assert.assertEquals(4, elements.size()); } @Test public void getTextTest() throws Exception { iface.go(testPage); WebDriverElement span = $("#writingSpan"); Assert.assertEquals("Click button to hide me", span.getText()); WebDriverElement paragraph = $("#intervalPara"); Assert.assertEquals("Click to make me blink", paragraph.getText()); WebDriverElement input = iface.getWebDriverElement(Strategy.NAME, "namedInput"); Assert.assertEquals("This is named input 0", input.getText()); } @Test public void getSelectTest() throws Exception { iface.go(testPage); WebDriverElement formElement = $("#formDiv #form"); WebDriverSelector actualSelectElement = (WebDriverSelector) formElement.getSelect(new Hook(Strategy.TAG, "select"), 0); Assert.assertEquals("Option 1", actualSelectElement.getFirstSelectedOption()); } @Test public void containsTest() throws Exception { final boolean CASE_SENSITIVE = true; final boolean CASE_INSENSITIVE = false; iface.go(testPage); final WebDriverElement writingDiv = $("#clickToHideDiv"); Assert.assertTrue(writingDiv.contains("Click button", CASE_SENSITIVE)); Assert.assertTrue(writingDiv.contains("cLiCk BuTtOn", CASE_INSENSITIVE)); Assert.assertTrue(writingDiv.contains("Click button", CASE_INSENSITIVE)); Assert.assertFalse(writingDiv.contains("cLiCk BuTtOn", CASE_SENSITIVE)); Assert.assertFalse(writingDiv.contains("Doesn't contain this", CASE_SENSITIVE)); Assert.assertFalse(writingDiv.contains("Doesn't contain this", CASE_INSENSITIVE)); } @Test public void doubleClickTest() throws Exception { iface.go(testPage); WebDriverElement doubleClickText = $("#doubleOrRightClickDiv #doubleClickText"); // Double clicking paragraph makes it disappear doubleClickText.doubleClick(); Assert.assertFalse(doubleClickText.isDisplayed()); } @Ignore("We don't currently have a good way to include drag and drop. " + "Selenium doesn't currently support HTML5 native drag and drop" + "and we don't want to import an entire library for just one test.") @Test public void dragNDropTest() throws Exception { String url = "http://demos111.mootools.net/DragDrop"; iface.go(url); WebDriverElement dragElement = $(".drag"); WebDriverElement dropElement = $(".drop"); Assert.assertTrue("100px".equals(dropElement.getCssValue("height"))); dragElement.dragNDrop(dropElement); iface.pause(1000); Assert.assertTrue("130px".equals(dropElement.getCssValue("height"))); } @Test public void pauseUntilVisibleTest() throws Exception { iface.go(testPage); WebDriverElement text = $("#clickToToggleVisibilityDiv #intervalPara"); text.click(); Assert.assertNotNull(iface.getPause().waitForVisible(new Hook(Strategy.ID, "intervalPara"), 2000)); Assert.assertTrue(text.isDisplayed()); // Wait for the text to go invisible again iface.pause(1000); Assert.assertNotNull(iface.getPause().waitForVisible( $("#clickToToggleVisibilityDiv #intervalPara"))); Assert.assertTrue(text.isDisplayed()); // Look for a nonexistent element to get time out, set the implicit wait to 0 // so that searching for the element returns immediately when it doesn't find it iface.wd.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); thrown.expect(CandybeanException.class); iface.getPause().waitForVisible($("#NonExistentElement")); } @Test public void pauseUntilInvisibleTest() throws Exception { iface.go(testPage); // Clicking intervalPara makes it toggle visibility every second WebDriverElement text = $("#clickToToggleVisibilityDiv #intervalPara"); text.click(); iface.getPause().waitForInvisible(new Hook(Strategy.ID, "intervalPara"), 2000); Assert.assertTrue(!text.isDisplayed()); // Force a timeout on a visible element thrown.expect(CandybeanException.class); iface.getPause().waitForInvisible($("#clickToToggleVisibilityDiv #clickPara"), 100); } @Test public void pauseUntilClickableTest() throws Exception { iface.go(testPage); // Clicking intervalPara makes it toggle visibility every second $("#clickToToggleVisibilityDiv #intervalPara").click(); Assert.assertNotNull(iface.getPause().waitUntil(WaitConditions.clickable( $("#clickToToggleVisibilityDiv #intervalPara")))); // Look for a nonexistent element to get time out, set the implicit wait to 0 // so that searching for the element returns immediately when it doesn't find it iface.wd.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); thrown.expect(CandybeanException.class); iface.getPause().waitUntil(WaitConditions.clickable(new Hook(Strategy.ID, "NonExistentElement")), 500); } @Test public void hoverTest() throws Exception { iface.go(testPage); WebDriverElement hoverElement = $("#hoverableDiv #hoverElement"); // Hovering over hoverElement makes it invisible hoverElement.hover(); Assert.assertFalse(hoverElement.isDisplayed()); } @Test public void isDisplayedTest() throws Exception { iface.go(testPage); WebDriverElement clickPara = $("#clickToToggleVisibilityDiv #clickPara"); Assert.assertTrue(clickPara.isDisplayed()); // Clicking clickPara toggles its visibility clickPara.click(); Assert.assertFalse(clickPara.isDisplayed()); } @Test public void rightClickTest() throws Exception { iface.go(testPage); WebDriverElement rightClickText = $("#doubleOrRightClickDiv #rightClickText"); // Right clicking rightClickText toggles its visibility rightClickText.rightClick(); // Second right click to cancel the menu rightClickText.rightClick(); Assert.assertFalse(rightClickText.isDisplayed()); } @Test public void sendStringTest() throws Exception { final String garbageString = "This string is garbage that needs to be cleared."; final String searchString = "sugarcrm"; iface.go(testPage); WebDriverElement textField = $("#formDiv #formInput"); // clear and set scenario textField.sendString(garbageString); textField.sendString(searchString); Assert.assertEquals(searchString, textField.getText()); // append scenario -- base test and append assert String searchString1 = "sugar"; String searchString2 = "con"; textField.sendString(searchString1); textField.sendString(searchString2, true); Assert.assertEquals(searchString1 + searchString2, textField.getText()); // clear and set to empty string scenario String emptyString = ""; textField.sendString(emptyString); Assert.assertEquals(emptyString, textField.getText()); } @Test public void executeJavascriptTest() throws CandybeanException { iface.go(testPage); WebDriverElement formInput = $("#formDiv #formInput"); String searchTerm = "This is a search term"; formInput.executeJavascript("arguments[0].value = '" + searchTerm + "';"); Assert.assertTrue(formInput.getAttribute("value").equals(searchTerm)); String boxContents = (String) (formInput.executeJavascript("return arguments[0].value;")); Assert.assertEquals("Javascript return value incorrect. Expected: " + searchTerm + " Found: " + boxContents, boxContents, searchTerm); } @Test public void getWidthTest() throws CandybeanException { iface.go(testPage); WebDriverElement element = $("#formInput"); Assert.assertTrue(element.getWidth() > 1); } @Test public void getHeightTest() throws CandybeanException { iface.go(testPage); WebDriverElement element = $("#formInput"); Assert.assertTrue(element.getHeight() > 1); } @Test public void getCssValueTest() throws CandybeanException { iface.go(testPage); WebDriverElement textField = $("#formInput"); Assert.assertEquals("inline-block", textField.getCssValue("display")); } @Test public void waitForAttribute() throws Exception { final Hook paragraph = new Hook(Strategy.ID, "intervalPara"); final boolean HAS_ATTRIBUTE = true; final boolean DOESNT_HAVE_ATTRIBUTE = false; iface.go(testPage); // Clicking on paragraph toggles its class between hidden and normal every second iface.getWebDriverElement(paragraph).click(); Assert.assertNotNull(iface.getPause().waitForAttribute(paragraph, "class", "hidden", HAS_ATTRIBUTE, 10000)); Assert.assertNotNull(iface.getPause().waitForAttribute(paragraph, "class", "hidden", DOESNT_HAVE_ATTRIBUTE, 10000)); Assert.assertNotNull(iface.getPause().waitForAttribute(paragraph, "class", "normal", DOESNT_HAVE_ATTRIBUTE, 10000)); Assert.assertNotNull(iface.getPause().waitForAttribute(paragraph, "class", "normal", HAS_ATTRIBUTE, 10000)); } @Test public void waitForRegexAttribute() throws Exception { final Hook paragraph = new Hook(Strategy.ID, "intervalPara"); final boolean HAS_ATTRIBUTE = true; final boolean DOESNT_HAVE_ATTRIBUTE = false; iface.go(testPage); // Clicking on paragraph toggles its class between hidden and normal every second iface.getWebDriverElement(paragraph).click(); Assert.assertNotNull(iface.getPause().waitForRegexAttribute(paragraph, "class", "h.*n", HAS_ATTRIBUTE, 10000)); Assert.assertNotNull(iface.getPause().waitForRegexAttribute(paragraph, "class", ".idden", DOESNT_HAVE_ATTRIBUTE, 10000)); Assert.assertNotNull(iface.getPause().waitForRegexAttribute(paragraph, "class", "n.*l", DOESNT_HAVE_ATTRIBUTE)); Assert.assertNotNull(iface.getPause().waitForRegexAttribute(paragraph, "class", "normal", DOESNT_HAVE_ATTRIBUTE)); } @Test public void waitForOnScreen() throws Exception { final boolean IS_ON_SCREEN = true; final boolean IS_OFF_SCREEN = false; final Hook paragraph = new Hook(Strategy.ID, "p1"); iface.go("file://" + System.getProperty("user.dir") + "/resources/html/test/onOffScreen.html"); /* Clicking on paragraph * Changes its coordinates to (-50,-50) * Wait 1 second * Changes its coordinates to (50,50) * Repeat */ iface.getWebDriverElement(paragraph).click(); Assert.assertTrue(iface.getPause().waitForOnScreen(paragraph, IS_ON_SCREEN).isOnScreen()); Assert.assertFalse(iface.getPause().waitForOnScreen(paragraph, IS_OFF_SCREEN).isOnScreen()); Assert.assertTrue(iface.getPause().waitForOnScreen(paragraph, IS_ON_SCREEN).isOnScreen()); // There are 3 static svgs on the page. svg1 is entirely on the screen, svg2 is entirely off, svg3 is half on Assert.assertTrue(iface.getPause().waitForOnScreen(new Hook(Strategy.ID, "svg1"), IS_ON_SCREEN).isOnScreen()); Assert.assertFalse(iface.getPause().waitForOnScreen(new Hook(Strategy.ID, "svg2"), IS_OFF_SCREEN).isOnScreen()); Assert.assertTrue(iface.getPause().waitForOnScreen(new Hook(Strategy.ID, "svg3"), IS_ON_SCREEN).isOnScreen()); } @Test public void toggleWaitForElement() throws Exception { final Hook writingHook = new Hook(Strategy.ID, "writingSpan"); iface.go(testPage); // Clicking this button toggles the visibility of the element found by writing hook final WebDriverElement button = iface.getWebDriverElement(new Hook(Strategy.ID, "toggleWritingButton")); Assert.assertTrue(iface.getPause().waitForElement(writingHook).isDisplayed()); button.click(); // Look for a nonexistent element to get time out, set the implicit wait to 0 // so that searching for the element returns immediately when it doesn't find it iface.wd.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); iface.getPause().waitForElementRemoved(writingHook); Assert.assertEquals(0, iface.getWebDriverElements(writingHook).size()); button.click(); Assert.assertTrue(iface.getPause().waitForElement(writingHook).isDisplayed()); button.click(); iface.getPause().waitForElementRemoved(writingHook); } @Test public void getSourceTest() throws CandybeanException { iface.go(testPage); final WebDriverElement searchBox = $("#clickToHideDiv"); final String found = searchBox.getSource(); final String expected = "id=\"writingSpan\""; Assert.assertTrue("Src did not contain " + expected + "\nFound source:\n" + found, found.contains(expected)); } }