1 package org.apache.archiva.web.test.parent;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.web.test.tools.ArchivaSeleniumExecutionRule;
23 import org.apache.archiva.web.test.tools.WebdriverUtility;
24 import org.junit.Assert;
25 import org.junit.Rule;
26 import org.openqa.selenium.*;
27 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
28 import org.openqa.selenium.interactions.Actions;
29 import org.openqa.selenium.support.ui.ExpectedConditions;
30 import org.openqa.selenium.support.ui.Select;
31 import org.openqa.selenium.support.ui.WebDriverWait;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 import java.io.IOException;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.nio.file.Paths;
39 import java.text.SimpleDateFormat;
40 import java.util.ArrayList;
41 import java.util.Date;
42 import java.util.Iterator;
43 import java.util.List;
45 import java.util.Map.Entry;
46 import java.util.Properties;
47 import java.util.function.Function;
50 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
54 public abstract class AbstractSeleniumTest
56 private final Logger logger = LoggerFactory.getLogger( getClass() );
59 public ArchivaSeleniumExecutionRule archivaSeleniumExecutionRule = new ArchivaSeleniumExecutionRule();
61 public String browser = System.getProperty( "browser" );
63 public String baseUrl =
64 "http://localhost:" + System.getProperty( "container.http.port" ) + "/archiva/index.html?request_lang=en";
66 public int maxWaitTimeInMs = Integer.getInteger( "maxWaitTimeInMs" );
68 public String seleniumHost = System.getProperty( "seleniumHost", "localhost" );
70 public int seleniumPort = Integer.getInteger( "seleniumPort", 4444 );
72 public boolean remoteSelenium = Boolean.parseBoolean( System.getProperty( "seleniumRemote", "false" ) );
74 WebDriver webDriver = null;
79 * this method is called by the Rule before executing a test
87 p.load( this.getClass().getClassLoader().getResourceAsStream( "test.properties" ) );
89 baseUrl = WebdriverUtility.getBaseUrl()+"/index.html?request_lang=en";
90 open( baseUrl, browser, seleniumHost, seleniumPort, maxWaitTimeInMs, remoteSelenium );
91 getWebDriver().manage().window().maximize();
96 * this method is called by the Rule after executing a tests
100 getWebDriver().close();
104 * Initialize selenium
106 public void open( String baseUrl, String browser, String seleniumHost, int seleniumPort, int maxWaitTimeInMs, boolean remoteSelenium)
111 if ( getWebDriver() == null )
113 WebDriver driver = WebdriverUtility.newWebDriver(browser, seleniumHost, seleniumPort, remoteSelenium);
115 // selenium.setTimeout( Integer.toString( maxWaitTimeInMs ) );
116 this.webDriver = driver;
119 catch ( Exception e )
122 System.out.print( e.getMessage() );
127 public void assertAdminCreated()
130 initializeArchiva( baseUrl, browser, maxWaitTimeInMs, seleniumHost, seleniumPort, remoteSelenium );
133 public void loadPage(String url, int timeout) {
134 getWebDriver().get( url );
135 WebDriverWait wait = new WebDriverWait( getWebDriver(), timeout );
136 wait.until( new Function<WebDriver, Boolean>()
138 public Boolean apply( WebDriver driver )
140 return ( (JavascriptExecutor) driver ).executeScript( "return document.readyState" ).equals( "complete" );
146 public void initializeArchiva( String baseUrl, String browser, int maxWaitTimeInMs, String seleniumHost,
147 int seleniumPort, boolean remoteSelenium)
151 open( baseUrl, browser, seleniumHost, seleniumPort, maxWaitTimeInMs, remoteSelenium);
152 loadPage(baseUrl, 30);
153 WebDriverWait wait = new WebDriverWait(getWebDriver(),30);
154 wait.until(ExpectedConditions.presenceOfElementLocated(By.id("topbar-menu")));
156 wait = new WebDriverWait( getWebDriver(), 20 );
157 Boolean found = wait.until( ExpectedConditions.or(
158 ExpectedConditions.visibilityOfElementLocated(By.id("create-admin-link-a")),
159 ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a"))));
163 WebElement adminLink = getWebDriver().findElement( By.id( "create-admin-link-a" ) );
164 WebElement loginLink = getWebDriver().findElement( By.id( "login-link-a" ) );
166 // if not admin user created create one
167 if ( adminLink != null && adminLink.isDisplayed() )
170 Assert.assertFalse( isElementVisible( "login-link-a" ) );
171 Assert.assertFalse( isElementVisible( "register-link-a" ) );
172 // skygo need to set to true for passing is that work as expected ?
174 wait = new WebDriverWait( getWebDriver(), 10 );
175 wait.until( ExpectedConditions.visibilityOfElementLocated( By.id( "user-create" ) ) );
177 String fullname = getProperty( "ADMIN_FULLNAME" );
178 String username = getAdminUsername();
179 String mail = getProperty( "ADMIN_EMAIL" );
180 String password = getProperty( "ADMIN_PASSWORD" );
181 submitAdminData( fullname, mail, password );
182 assertUserLoggedIn( username );
183 clickLinkWithLocator( "logout-link-a", false );
185 else if ( loginLink != null && loginLink.isDisplayed() )
187 Assert.assertTrue( isElementVisible( "login-link-a" ) );
188 Assert.assertTrue( isElementVisible( "register-link-a" ) );
189 login( getAdminUsername(), getAdminPassword() );
195 public WebDriver getWebDriver() {
196 return this.webDriver;
199 protected String getProperty( String key )
201 return p.getProperty( key );
204 public String getAdminUsername()
206 String adminUsername = getProperty( "ADMIN_USERNAME" );
207 return adminUsername;
210 public String getAdminPassword()
212 String adminPassword = getProperty( "ADMIN_PASSWORD" );
213 return adminPassword;
216 public void submitAdminData( String fullname, String email, String password )
218 setFieldValue( "fullname", fullname );
219 setFieldValue( "email", email );
220 setFieldValue( "password", password );
221 setFieldValue( "confirmPassword", password );
222 clickButtonWithLocator( "user-create-form-register-button" , false);
225 public void login( String username, String password )
227 login( username, password, true, "Login Page" );
230 public void login( String username, String password, boolean valid, String assertReturnPage )
232 if ( isElementVisible( "login-link-a" ) )//isElementPresent( "loginLink" ) )
236 submitLoginPage( username, password, false, valid, assertReturnPage );
240 assertUserLoggedIn( username );
245 public void goToLoginPage()
247 logger.info("Goto login page");
248 loadPage(baseUrl, 30);
249 WebDriverWait wait = new WebDriverWait(getWebDriver(),30);
250 wait.until(ExpectedConditions.presenceOfElementLocated(By.id("topbar-menu")));
251 wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(By.id("logout-link")),
252 ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a"))));
254 // are we already logged in ?
255 if ( isElementVisible( "logout-link" ) ) //isElementPresent( "logoutLink" ) )
257 logger.info("Logging out ");
259 clickLinkWithLocator( "logout-link-a", false );
261 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a")));
262 clickLinkWithLocator( "login-link-a", false );
263 // This is a workaround for bug with HTMLUnit. The display attribute of the
264 // login dialog is not changed via the click.
265 // TODO: Check after changing jquery, bootstrap or htmlunit version
266 if (getWebDriver() instanceof HtmlUnitDriver)
268 ( (JavascriptExecutor) getWebDriver() ).executeScript( "$('#modal-login').show();" );
271 wait = new WebDriverWait(getWebDriver(),20);
272 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("modal-login")));
277 public void assertLoginModal()
279 assertElementPresent( "user-login-form" );
280 Assert.assertTrue( isElementVisible( "register-link" ) );
281 Assert.assertTrue( isElementVisible("user-login-form-username" ));
282 Assert.assertTrue( isElementVisible("user-login-form-password" ));
283 assertButtonWithIdPresent( "modal-login-ok" );
284 Assert.assertTrue( isElementVisible( "modal-login-ok" ));
288 public void submitLoginPage( String username, String password )
290 submitLoginPage( username, password, false, true, "Login Page" );
293 public void submitLoginPage( String username, String password, boolean validUsernamePassword )
295 submitLoginPage( username, password, false, validUsernamePassword, "Login Page" );
298 public void submitLoginPage( String username, String password, boolean rememberMe, boolean validUsernamePassword,
299 String assertReturnPage )
301 logger.info("Activating login form");
302 // clickLinkWithLocator( "login-link-a", false);
303 WebDriverWait wait = new WebDriverWait(getWebDriver(),5);
304 WebElement usernameField = wait.until(ExpectedConditions.visibilityOf(getWebDriver().findElement(By.id("user-login-form-username"))));
305 wait = new WebDriverWait(getWebDriver(),5);
306 WebElement passwordField = wait.until(ExpectedConditions.visibilityOf(getWebDriver().findElement(By.id("user-login-form-password"))));
307 wait = new WebDriverWait(getWebDriver(),5);
308 WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("modal-login-ok")));
309 usernameField.sendKeys(username);
310 passwordField.sendKeys(password);
314 checkField( "rememberMe" );
318 if ( validUsernamePassword )
320 assertUserLoggedIn( username );
325 if ( "Login Page".equals( assertReturnPage ) )
331 assertPage( assertReturnPage );
336 // *******************************************************
337 // Auxiliar methods. This method help us and simplify test.
338 // *******************************************************
340 protected void assertUserLoggedIn( String username )
342 WebDriverWait wait = new WebDriverWait(getWebDriver(), 10);
343 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("logout-link")));
344 Assert.assertFalse( isElementVisible( "login-link" ) );
345 Assert.assertFalse( isElementVisible( "register-link" ) );
346 Assert.assertFalse( isElementVisible( "create-admin-link" ) );
349 public void assertCreateAdmin()
351 assertElementPresent( "user-create" );
352 assertFieldValue( "admin", "username" );
353 assertElementPresent( "fullname" );
354 assertElementPresent( "password" );
355 assertElementPresent( "confirmPassword" );
356 assertElementPresent( "email" );
359 public void assertFieldValue( String fieldValue, String fieldName )
361 assertElementPresent( fieldName );
362 Assert.assertEquals( fieldValue, findElement(fieldName ).getAttribute( "value") );
365 public void assertPage( String title )
367 Assert.assertEquals( title, getTitle());
370 public String getTitle()
373 return getWebDriver().getTitle().replaceAll( "[ \n\r]+", " " );
376 public String getHtmlContent()
378 return getWebDriver().getPageSource();
381 public String getText( String locator )
383 return findElement(locator ).getText();
386 public void assertTextPresent( String text )
388 Assert.assertTrue( "'" + text + "' isn't present.", getWebDriver().getPageSource().contains( text ) );
392 public void assertTextNotPresent( String text )
394 Assert.assertFalse( "'" + text + "' is present.", isTextPresent( text ) );
397 public void assertElementPresent( String elementLocator )
399 Assert.assertTrue( "'" + elementLocator + "' isn't present.", isElementPresent( elementLocator ) );
402 public void assertElementNotPresent( String elementLocator )
404 Assert.assertFalse( "'" + elementLocator + "' is present.", isElementPresent( elementLocator ) );
407 public void assertLinkPresent( String text )
409 Assert.assertTrue( "The link '" + text + "' isn't present.", isElementPresent( "//*[text()='" + text+"']//ancestor::a" ) );
412 public void assertLinkNotPresent( String text )
414 Assert.assertFalse( "The link('" + text + "' is present.", isElementPresent( "//*[text()='" + text+"']//ancestor::a" ) );
417 public void assertLinkNotVisible( String text )
419 Assert.assertFalse( "The link('" + text + "' is visible.", isElementVisible( "//*[text()='" + text+"']//ancestor::a" ) );
422 public void assertLinkVisible( String text )
424 Assert.assertTrue( "The link('" + text + "' is not visible.", isElementVisible( "//*[text()='" + text+"']//ancestor::a" ) );
427 public void assertImgWithAlt( String alt )
429 assertElementPresent( "/¯img[@alt='" + alt + "']" );
432 public void assertImgWithAltAtRowCol( boolean isALink, String alt, int row, int column )
434 String locator = "//tr[" + row + "]/td[" + column + "]/";
435 locator += isALink ? "a/" : "";
436 locator += "img[@alt='" + alt + "']";
438 assertElementPresent( locator );
441 public void assertImgWithAltNotPresent( String alt )
443 assertElementNotPresent( "/¯img[@alt='" + alt + "']" );
448 public boolean isTextPresent( String text )
450 return getWebDriver().getPageSource().contains(text);
453 public boolean isLinkPresent( String text )
455 return isElementPresent( "//*[text()='" + text +"']//ancestor::a" );
458 public boolean isElementPresent( String locator )
462 return findElement(locator ) != null;
463 } catch (Exception e) {
468 public boolean isElementVisible(String locator )
471 return findElement(locator).isDisplayed();
472 } catch (Exception e) {
478 public void waitPage()
480 // TODO define a smaller maxWaitTimeJsInMs for wait javascript response for browser side validation
481 //getSelenium().w .wait( Long.parseLong( maxWaitTimeInMs ) );
482 //getSelenium().waitForPageToLoad( maxWaitTimeInMs );
483 // http://jira.openqa.org/browse/SRC-302
484 // those hack looks to break some tests :-(
485 // getSelenium().waitForCondition( "selenium.isElementPresent('document.body');", maxWaitTimeInMs );
486 //getSelenium().waitForCondition( "selenium.isElementPresent('footer');", maxWaitTimeInMs );
487 //getSelenium().waitForCondition( "selenium.browserbot.getCurrentWindow().document.getElementById('footer')",
488 // maxWaitTimeInMs );
489 // so the only hack is to not use a too small wait time
493 Thread.sleep( maxWaitTimeInMs );
495 catch ( InterruptedException e )
497 throw new RuntimeException( "issue on Thread.sleep : " + e.getMessage(), e );
501 public String getFieldValue( String fieldName )
503 return findElement(fieldName ).getAttribute( "value" );
507 public WebElement selectValue( String locator, String value) {
508 return this.selectValue( locator, value, false );
511 public WebElement selectValue( String locator, String value, boolean scrollToView )
514 boolean check = true;
515 WebDriverWait wait = new WebDriverWait( getWebDriver( ), 10 );
516 WebElement element = null;
517 while(check && count-->0)
521 element = findElement( locator );
522 List<WebElement> elementList = new ArrayList<>( );
523 elementList.add( element );
524 wait.until( ExpectedConditions.visibilityOfAllElements( elementList ) );
526 } catch (Throwable e) {
527 logger.info("Waiting for select element {} to be visible", locator);
530 Select select = new Select(element);
531 select.selectByValue( value );
535 public WebElement findElement(String locator) {
536 if (locator.startsWith("/")) {
537 return getWebDriver().findElement( By.xpath( locator ) );
539 return getWebDriver().findElement( By.id(locator) );
546 clickLinkWithXPath( "//input[@type='submit']" );
549 public void assertButtonWithValuePresent( String text )
551 Assert.assertTrue( "'" + text + "' button isn't present", isButtonWithValuePresent( text ) );
554 public void assertButtonWithIdPresent( String id )
556 Assert.assertTrue( "'Button with id =" + id + "' isn't present", isButtonWithIdPresent( id ) );
559 public void assertButtonWithValueNotPresent( String text )
561 Assert.assertFalse( "'" + text + "' button is present", isButtonWithValuePresent( text ) );
564 public boolean isButtonWithValuePresent( String text )
566 return isElementPresent( "//button[@value='" + text + "']" ) || isElementPresent(
567 "//input[@value='" + text + "']" );
570 public boolean isButtonWithIdPresent( String text )
572 return isElementPresent( "//button[@id='" + text + "']" ) || isElementPresent( "//input[@id='" + text + "']" );
575 public void clickButtonWithName( String text, boolean wait )
577 clickLinkWithXPath( "//input[@name='" + text + "']", wait );
580 public void clickButtonWithValue( String text )
582 clickButtonWithValue( text, false );
585 public void clickButtonWithValue( String text, boolean wait )
587 assertButtonWithValuePresent( text );
589 if ( isElementPresent( "//button[@value='" + text + "']" ) )
591 clickLinkWithXPath( "//button[@value='" + text + "']", wait );
595 clickLinkWithXPath( "//input[@value='" + text + "']", wait );
599 public void clickSubmitWithLocator( String locator )
601 clickLinkWithLocator( locator );
604 public void clickSubmitWithLocator( String locator, boolean wait )
606 clickLinkWithLocator( locator, wait );
609 public void clickImgWithAlt( String alt )
611 clickLinkWithLocator( "//img[@alt='" + alt + "']" );
614 public void clickLinkWithText( String text )
616 clickLinkWithText( text, false );
619 public void clickLinkWithText( String text, boolean wait )
621 clickLinkWithLocator( "//*[text()='" + text +"']//ancestor::a", wait );
624 public void clickLinkWithXPath( String xpath )
626 clickLinkWithXPath( xpath, false );
629 public void clickLinkWithXPath( String xpath, boolean wait )
631 clickLinkWithLocator( xpath, wait );
634 public void clickLinkWithLocator( String locator )
636 clickLinkWithLocator( locator, false );
639 public void clickLinkWithLocator( String locator, boolean wait )
641 assertElementPresent( locator );
642 findElement(locator).click();
649 public void clickButtonWithLocator( String locator )
651 clickButtonWithLocator( locator, false );
654 public void clickButtonWithLocator( String locator, boolean wait )
656 assertElementPresent( locator );
657 findElement(locator ).click();
664 public <V> V tryClick(By clickableLocator, Function<? super WebDriver, V> conditions, String message, int attempts, int maxWaitTimeInS) {
666 getWebDriver().manage().window().maximize();
667 int count = attempts;
668 WebDriverWait wait = new WebDriverWait( getWebDriver(), maxWaitTimeInS );
671 WebElement el = null;
676 el = wait.until(ExpectedConditions.elementToBeClickable( clickableLocator ));
677 Actions actions = new Actions(getWebDriver());
678 actions.moveToElement(el).click().perform();
679 result = wait.until( conditions );
681 } catch (Exception e) {
682 logger.info("Error: {}, {}, {}",count,e.getClass().getName(), e.getMessage());
684 // Elements may be stale and throw an exception, if the location is requested
687 Point elLoc = el.getLocation();
688 logger.info( "Location: x={} y={}", elLoc.getX(), elLoc.getY() );
689 } catch (Throwable e2) {
690 logger.info("Could not determine location");
698 Thread.currentThread().sleep(500);
700 catch ( InterruptedException e )
706 Assert.fail( message);
712 * Executes click() on the WebElement <code>el</code> and waits for the conditions.
713 * If the condition is not fulfilled in <code>maxWaitTimeInS</code>, the click is executed again
714 * and waits again for the condition.
715 * After the number of attempts as given by the parameter an assertion error will be thrown, with
716 * the given <code>message</code>.
718 * If the click was successful the element is returned that was created by the condition.
720 * @param el The element where the click is executed
721 * @param conditions The conditions to wait for after the click
722 * @param message The assertion messages
723 * @param attempts Maximum number of click attempts
724 * @param maxWaitTimeInS The time in seconds to wait that the condition is fulfilled.
725 * @param <V> The return type
728 public <V> V tryClick( WebElement el, Function<? super WebDriver, V> conditions, String message, int attempts, int maxWaitTimeInS)
730 int count = attempts;
731 WebDriverWait wait = new WebDriverWait( getWebDriver(), maxWaitTimeInS );
736 if (count<attempts) {
739 result = conditions.apply( getWebDriver() );
741 } catch (Exception e) {
748 result = wait.until( conditions );
750 } catch (Exception e) {
751 logger.info("Error: {}, {}",count, e.getMessage());
757 Thread.currentThread().sleep(500);
759 catch ( InterruptedException e )
765 Assert.fail( message);
770 public <V> V tryClick(WebElement el, Function<? super WebDriver, V> conditions, String message, int attempts )
772 return tryClick( el, conditions, message, attempts, 10 );
775 public <V> V tryClick(WebElement el, Function<? super WebDriver, V> conditions, String message)
777 return tryClick( el, conditions, message, 3);
781 public void setFieldValues( Map<String, String> fieldMap )
783 Map.Entry<String, String> entry;
785 for ( Iterator<Entry<String, String>> entries = fieldMap.entrySet().iterator(); entries.hasNext(); )
787 entry = entries.next();
789 setFieldValue( entry.getKey(), entry.getValue() );
793 public void setFieldValue( String fieldName, String value )
795 findElement(fieldName ).sendKeys( value );
798 public void checkField( String locator )
800 WebElement element = findElement(locator );
801 if (!element.isSelected()) {
806 public void uncheckField( String locator )
808 WebElement element = findElement(locator );
809 if (element.isSelected()) {
814 public boolean isChecked( String locator )
816 return findElement(locator ).isSelected();
819 public void assertIsChecked( String locator )
822 Assert.assertTrue( isChecked( locator ));
825 public void assertIsNotChecked( String locator )
828 Assert.assertFalse( isChecked( locator ) );
833 public String captureScreenShotOnFailure( Throwable failure, String methodName, String className )
835 SimpleDateFormat sdf = new SimpleDateFormat( "yyyy.MM.dd-HH_mm_ss" );
836 String time = sdf.format( new Date() );
837 Path targetPath = Paths.get( "target", "screenshots" );
841 for ( StackTraceElement stackTrace : failure.getStackTrace() )
843 if ( stackTrace.getClassName().equals( this.getClass().getName() ) )
845 lineNumber = stackTrace.getLineNumber();
851 Files.createDirectories(targetPath);
852 } catch (IOException e) {
853 logger.error("Could not create directory {}: {}", targetPath, e.getMessage(), e);
855 if (getWebDriver()!=null)
857 String fileBaseName = methodName + "_" + className + ".java_" + lineNumber + "-" + time;
858 Path fileName = targetPath.resolve( fileBaseName + ".png" );
859 Path screenshot = WebdriverUtility.takeScreenShot( fileName.getFileName().toString(), getWebDriver());
860 return fileName.toAbsolutePath().toString();