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";
91 open( baseUrl, browser, seleniumHost, seleniumPort, maxWaitTimeInMs, remoteSelenium );
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);
153 loadPage(baseUrl, 30);
154 WebDriverWait wait = new WebDriverWait(getWebDriver(),30);
155 wait.until(ExpectedConditions.presenceOfElementLocated(By.id("topbar-menu")));
157 wait = new WebDriverWait( getWebDriver(), 20 );
158 Boolean found = wait.until( ExpectedConditions.or(
159 ExpectedConditions.visibilityOfElementLocated(By.id("create-admin-link-a")),
160 ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a"))));
164 WebElement adminLink = getWebDriver().findElement( By.id( "create-admin-link-a" ) );
165 WebElement loginLink = getWebDriver().findElement( By.id( "login-link-a" ) );
167 // if not admin user created create one
168 if ( adminLink != null && adminLink.isDisplayed() )
171 Assert.assertFalse( isElementVisible( "login-link-a" ) );
172 Assert.assertFalse( isElementVisible( "register-link-a" ) );
173 // skygo need to set to true for passing is that work as expected ?
175 wait = new WebDriverWait( getWebDriver(), 10 );
176 wait.until( ExpectedConditions.visibilityOfElementLocated( By.id( "user-create" ) ) );
178 String fullname = getProperty( "ADMIN_FULLNAME" );
179 String username = getAdminUsername();
180 String mail = getProperty( "ADMIN_EMAIL" );
181 String password = getProperty( "ADMIN_PASSWORD" );
182 submitAdminData( fullname, mail, password );
183 assertUserLoggedIn( username );
184 clickLinkWithLocator( "logout-link-a", false );
186 else if ( loginLink != null && loginLink.isDisplayed() )
188 Assert.assertTrue( isElementVisible( "login-link-a" ) );
189 Assert.assertTrue( isElementVisible( "register-link-a" ) );
190 login( getAdminUsername(), getAdminPassword() );
196 public WebDriver getWebDriver() {
197 return this.webDriver;
200 protected String getProperty( String key )
202 return p.getProperty( key );
205 public String getAdminUsername()
207 String adminUsername = getProperty( "ADMIN_USERNAME" );
208 return adminUsername;
211 public String getAdminPassword()
213 String adminPassword = getProperty( "ADMIN_PASSWORD" );
214 return adminPassword;
217 public void submitAdminData( String fullname, String email, String password )
219 setFieldValue( "fullname", fullname );
220 setFieldValue( "email", email );
221 setFieldValue( "password", password );
222 setFieldValue( "confirmPassword", password );
223 clickButtonWithLocator( "user-create-form-register-button" , false);
226 public void login( String username, String password )
228 login( username, password, true, "Login Page" );
231 public void login( String username, String password, boolean valid, String assertReturnPage )
233 if ( isElementVisible( "login-link-a" ) )//isElementPresent( "loginLink" ) )
237 submitLoginPage( username, password, false, valid, assertReturnPage );
241 assertUserLoggedIn( username );
246 public void goToLoginPage()
248 logger.info("Goto login page");
249 loadPage(baseUrl, 30);
250 WebDriverWait wait = new WebDriverWait(getWebDriver(),30);
251 wait.until(ExpectedConditions.presenceOfElementLocated(By.id("topbar-menu")));
252 wait.until(ExpectedConditions.or(ExpectedConditions.visibilityOfElementLocated(By.id("logout-link")),
253 ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a"))));
255 // are we already logged in ?
256 if ( isElementVisible( "logout-link" ) ) //isElementPresent( "logoutLink" ) )
258 logger.info("Logging out ");
260 clickLinkWithLocator( "logout-link-a", false );
262 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login-link-a")));
263 clickLinkWithLocator( "login-link-a", false );
264 // This is a workaround for bug with HTMLUnit. The display attribute of the
265 // login dialog is not changed via the click.
266 // TODO: Check after changing jquery, bootstrap or htmlunit version
267 if (getWebDriver() instanceof HtmlUnitDriver)
269 ( (JavascriptExecutor) getWebDriver() ).executeScript( "$('#modal-login').show();" );
272 wait = new WebDriverWait(getWebDriver(),20);
273 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("modal-login")));
278 public void assertLoginModal()
280 assertElementPresent( "user-login-form" );
281 Assert.assertTrue( isElementVisible( "register-link" ) );
282 Assert.assertTrue( isElementVisible("user-login-form-username" ));
283 Assert.assertTrue( isElementVisible("user-login-form-password" ));
284 assertButtonWithIdPresent( "modal-login-ok" );
285 Assert.assertTrue( isElementVisible( "modal-login-ok" ));
289 public void submitLoginPage( String username, String password )
291 submitLoginPage( username, password, false, true, "Login Page" );
294 public void submitLoginPage( String username, String password, boolean validUsernamePassword )
296 submitLoginPage( username, password, false, validUsernamePassword, "Login Page" );
299 public void submitLoginPage( String username, String password, boolean rememberMe, boolean validUsernamePassword,
300 String assertReturnPage )
302 logger.info("Activating login form");
303 // clickLinkWithLocator( "login-link-a", false);
304 WebDriverWait wait = new WebDriverWait(getWebDriver(),5);
305 WebElement usernameField = wait.until(ExpectedConditions.visibilityOf(getWebDriver().findElement(By.id("user-login-form-username"))));
306 wait = new WebDriverWait(getWebDriver(),5);
307 WebElement passwordField = wait.until(ExpectedConditions.visibilityOf(getWebDriver().findElement(By.id("user-login-form-password"))));
308 wait = new WebDriverWait(getWebDriver(),5);
309 WebElement button = wait.until(ExpectedConditions.elementToBeClickable(By.id("modal-login-ok")));
310 usernameField.sendKeys(username);
311 passwordField.sendKeys(password);
315 checkField( "rememberMe" );
319 if ( validUsernamePassword )
321 assertUserLoggedIn( username );
326 if ( "Login Page".equals( assertReturnPage ) )
332 assertPage( assertReturnPage );
337 // *******************************************************
338 // Auxiliar methods. This method help us and simplify test.
339 // *******************************************************
341 protected void assertUserLoggedIn( String username )
343 WebDriverWait wait = new WebDriverWait(getWebDriver(), 10);
344 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("logout-link")));
345 Assert.assertFalse( isElementVisible( "login-link" ) );
346 Assert.assertFalse( isElementVisible( "register-link" ) );
347 Assert.assertFalse( isElementVisible( "create-admin-link" ) );
350 public void assertCreateAdmin()
352 assertElementPresent( "user-create" );
353 assertFieldValue( "admin", "username" );
354 assertElementPresent( "fullname" );
355 assertElementPresent( "password" );
356 assertElementPresent( "confirmPassword" );
357 assertElementPresent( "email" );
360 public void assertFieldValue( String fieldValue, String fieldName )
362 assertElementPresent( fieldName );
363 Assert.assertEquals( fieldValue, findElement(fieldName ).getAttribute( "value") );
366 public void assertPage( String title )
368 Assert.assertEquals( title, getTitle());
371 public String getTitle()
374 return getWebDriver().getTitle().replaceAll( "[ \n\r]+", " " );
377 public String getHtmlContent()
379 return getWebDriver().getPageSource();
382 public String getText( String locator )
384 return findElement(locator ).getText();
387 public void assertTextPresent( String text )
389 Assert.assertTrue( "'" + text + "' isn't present.", getWebDriver().getPageSource().contains( text ) );
393 public void assertTextNotPresent( String text )
395 Assert.assertFalse( "'" + text + "' is present.", isTextPresent( text ) );
398 public void assertElementPresent( String elementLocator )
400 Assert.assertTrue( "'" + elementLocator + "' isn't present.", isElementPresent( elementLocator ) );
403 public void assertElementNotPresent( String elementLocator )
405 Assert.assertFalse( "'" + elementLocator + "' is present.", isElementPresent( elementLocator ) );
408 public void assertLinkPresent( String text )
410 Assert.assertTrue( "The link '" + text + "' isn't present.", isElementPresent( "//*[text()='" + text+"']//ancestor::a" ) );
413 public void assertLinkNotPresent( String text )
415 Assert.assertFalse( "The link('" + text + "' is present.", isElementPresent( "//*[text()='" + text+"']//ancestor::a" ) );
418 public void assertLinkNotVisible( String text )
420 Assert.assertFalse( "The link('" + text + "' is visible.", isElementVisible( "//*[text()='" + text+"']//ancestor::a" ) );
423 public void assertLinkVisible( String text )
425 Assert.assertTrue( "The link('" + text + "' is not visible.", isElementVisible( "//*[text()='" + text+"']//ancestor::a" ) );
428 public void assertImgWithAlt( String alt )
430 assertElementPresent( "/¯img[@alt='" + alt + "']" );
433 public void assertImgWithAltAtRowCol( boolean isALink, String alt, int row, int column )
435 String locator = "//tr[" + row + "]/td[" + column + "]/";
436 locator += isALink ? "a/" : "";
437 locator += "img[@alt='" + alt + "']";
439 assertElementPresent( locator );
442 public void assertImgWithAltNotPresent( String alt )
444 assertElementNotPresent( "/¯img[@alt='" + alt + "']" );
449 public boolean isTextPresent( String text )
451 return getWebDriver().getPageSource().contains(text);
454 public boolean isLinkPresent( String text )
456 return isElementPresent( "//*[text()='" + text +"']//ancestor::a" );
459 public boolean isElementPresent( String locator )
463 return findElement(locator ) != null;
464 } catch (Exception e) {
469 public boolean isElementVisible(String locator )
472 return findElement(locator).isDisplayed();
473 } catch (Exception e) {
479 public void waitPage()
481 // TODO define a smaller maxWaitTimeJsInMs for wait javascript response for browser side validation
482 //getSelenium().w .wait( Long.parseLong( maxWaitTimeInMs ) );
483 //getSelenium().waitForPageToLoad( maxWaitTimeInMs );
484 // http://jira.openqa.org/browse/SRC-302
485 // those hack looks to break some tests :-(
486 // getSelenium().waitForCondition( "selenium.isElementPresent('document.body');", maxWaitTimeInMs );
487 //getSelenium().waitForCondition( "selenium.isElementPresent('footer');", maxWaitTimeInMs );
488 //getSelenium().waitForCondition( "selenium.browserbot.getCurrentWindow().document.getElementById('footer')",
489 // maxWaitTimeInMs );
490 // so the only hack is to not use a too small wait time
494 Thread.sleep( maxWaitTimeInMs );
496 catch ( InterruptedException e )
498 throw new RuntimeException( "issue on Thread.sleep : " + e.getMessage(), e );
502 public String getFieldValue( String fieldName )
504 return findElement(fieldName ).getAttribute( "value" );
508 public WebElement selectValue( String locator, String value) {
509 return this.selectValue( locator, value, false );
512 public WebElement selectValue( String locator, String value, boolean scrollToView )
515 boolean check = true;
516 WebDriverWait wait = new WebDriverWait( getWebDriver( ), 10 );
517 WebElement element = null;
518 while(check && count-->0)
522 element = findElement( locator );
523 List<WebElement> elementList = new ArrayList<>( );
524 elementList.add( element );
525 wait.until( ExpectedConditions.visibilityOfAllElements( elementList ) );
527 } catch (Throwable e) {
528 logger.info("Waiting for select element {} to be visible", locator);
531 Select select = new Select(element);
532 select.selectByValue( value );
536 public WebElement findElement(String locator) {
537 if (locator.startsWith("/")) {
538 return getWebDriver().findElement( By.xpath( locator ) );
540 return getWebDriver().findElement( By.id(locator) );
547 clickLinkWithXPath( "//input[@type='submit']" );
550 public void assertButtonWithValuePresent( String text )
552 Assert.assertTrue( "'" + text + "' button isn't present", isButtonWithValuePresent( text ) );
555 public void assertButtonWithIdPresent( String id )
557 Assert.assertTrue( "'Button with id =" + id + "' isn't present", isButtonWithIdPresent( id ) );
560 public void assertButtonWithValueNotPresent( String text )
562 Assert.assertFalse( "'" + text + "' button is present", isButtonWithValuePresent( text ) );
565 public boolean isButtonWithValuePresent( String text )
567 return isElementPresent( "//button[@value='" + text + "']" ) || isElementPresent(
568 "//input[@value='" + text + "']" );
571 public boolean isButtonWithIdPresent( String text )
573 return isElementPresent( "//button[@id='" + text + "']" ) || isElementPresent( "//input[@id='" + text + "']" );
576 public void clickButtonWithName( String text, boolean wait )
578 clickLinkWithXPath( "//input[@name='" + text + "']", wait );
581 public void clickButtonWithValue( String text )
583 clickButtonWithValue( text, false );
586 public void clickButtonWithValue( String text, boolean wait )
588 assertButtonWithValuePresent( text );
590 if ( isElementPresent( "//button[@value='" + text + "']" ) )
592 clickLinkWithXPath( "//button[@value='" + text + "']", wait );
596 clickLinkWithXPath( "//input[@value='" + text + "']", wait );
600 public void clickSubmitWithLocator( String locator )
602 clickLinkWithLocator( locator );
605 public void clickSubmitWithLocator( String locator, boolean wait )
607 clickLinkWithLocator( locator, wait );
610 public void clickImgWithAlt( String alt )
612 clickLinkWithLocator( "//img[@alt='" + alt + "']" );
615 public void clickLinkWithText( String text )
617 clickLinkWithText( text, false );
620 public void clickLinkWithText( String text, boolean wait )
622 clickLinkWithLocator( "//*[text()='" + text +"']//ancestor::a", wait );
625 public void clickLinkWithXPath( String xpath )
627 clickLinkWithXPath( xpath, false );
630 public void clickLinkWithXPath( String xpath, boolean wait )
632 clickLinkWithLocator( xpath, wait );
635 public void clickLinkWithLocator( String locator )
637 clickLinkWithLocator( locator, false );
640 public void clickLinkWithLocator( String locator, boolean wait )
642 assertElementPresent( locator );
643 findElement(locator).click();
650 public void clickButtonWithLocator( String locator )
652 clickButtonWithLocator( locator, false );
655 public void clickButtonWithLocator( String locator, boolean wait )
657 assertElementPresent( locator );
658 findElement(locator ).click();
665 public <V> V tryClick(By clickableLocator, Function<? super WebDriver, V> conditions, String message, int attempts, int maxWaitTimeInS) {
667 getWebDriver().manage().window().maximize();
668 int count = attempts;
669 WebDriverWait wait = new WebDriverWait( getWebDriver(), maxWaitTimeInS );
672 WebElement el = null;
677 el = wait.until(ExpectedConditions.elementToBeClickable( clickableLocator ));
678 Actions actions = new Actions(getWebDriver());
679 actions.moveToElement(el).click().perform();
680 result = wait.until( conditions );
682 } catch (Exception e) {
683 logger.info("Error: {}, {}, {}",count,e.getClass().getName(), e.getMessage());
685 // Elements may be stale and throw an exception, if the location is requested
688 Point elLoc = el.getLocation();
689 logger.info( "Location: x={} y={}", elLoc.getX(), elLoc.getY() );
690 } catch (Throwable e2) {
691 logger.info("Could not determine location");
699 Thread.currentThread().sleep(500);
701 catch ( InterruptedException e )
707 Assert.fail( message);
713 * Executes click() on the WebElement <code>el</code> and waits for the conditions.
714 * If the condition is not fulfilled in <code>maxWaitTimeInS</code>, the click is executed again
715 * and waits again for the condition.
716 * After the number of attempts as given by the parameter an assertion error will be thrown, with
717 * the given <code>message</code>.
719 * If the click was successful the element is returned that was created by the condition.
721 * @param el The element where the click is executed
722 * @param conditions The conditions to wait for after the click
723 * @param message The assertion messages
724 * @param attempts Maximum number of click attempts
725 * @param maxWaitTimeInS The time in seconds to wait that the condition is fulfilled.
726 * @param <V> The return type
729 public <V> V tryClick( WebElement el, Function<? super WebDriver, V> conditions, String message, int attempts, int maxWaitTimeInS)
731 int count = attempts;
732 WebDriverWait wait = new WebDriverWait( getWebDriver(), maxWaitTimeInS );
737 if (count<attempts) {
740 result = conditions.apply( getWebDriver() );
742 } catch (Exception e) {
749 result = wait.until( conditions );
751 } catch (Exception e) {
752 logger.info("Error: {}, {}",count, e.getMessage());
758 Thread.currentThread().sleep(500);
760 catch ( InterruptedException e )
766 Assert.fail( message);
771 public <V> V tryClick(WebElement el, Function<? super WebDriver, V> conditions, String message, int attempts )
773 return tryClick( el, conditions, message, attempts, 10 );
776 public <V> V tryClick(WebElement el, Function<? super WebDriver, V> conditions, String message)
778 return tryClick( el, conditions, message, 3);
782 public void setFieldValues( Map<String, String> fieldMap )
784 Map.Entry<String, String> entry;
786 for ( Iterator<Entry<String, String>> entries = fieldMap.entrySet().iterator(); entries.hasNext(); )
788 entry = entries.next();
790 setFieldValue( entry.getKey(), entry.getValue() );
794 public void setFieldValue( String fieldName, String value )
796 findElement(fieldName ).sendKeys( value );
799 public void checkField( String locator )
801 WebElement element = findElement(locator );
802 if (!element.isSelected()) {
807 public void uncheckField( String locator )
809 WebElement element = findElement(locator );
810 if (element.isSelected()) {
815 public boolean isChecked( String locator )
817 return findElement(locator ).isSelected();
820 public void assertIsChecked( String locator )
823 Assert.assertTrue( isChecked( locator ));
826 public void assertIsNotChecked( String locator )
829 Assert.assertFalse( isChecked( locator ) );
834 public String captureScreenShotOnFailure( Throwable failure, String methodName, String className )
836 SimpleDateFormat sdf = new SimpleDateFormat( "yyyy.MM.dd-HH_mm_ss" );
837 String time = sdf.format( new Date() );
838 Path targetPath = Paths.get( "target", "screenshots" );
842 for ( StackTraceElement stackTrace : failure.getStackTrace() )
844 if ( stackTrace.getClassName().equals( this.getClass().getName() ) )
846 lineNumber = stackTrace.getLineNumber();
852 Files.createDirectories(targetPath);
853 } catch (IOException e) {
854 logger.error("Could not create directory {}: {}", targetPath, e.getMessage(), e);
856 if (getWebDriver()!=null)
858 String fileBaseName = methodName + "_" + className + ".java_" + lineNumber + "-" + time;
859 Path fileName = targetPath.resolve( fileBaseName + ".png" );
860 Path screenshot = WebdriverUtility.takeScreenShot( fileName.getFileName().toString(), getWebDriver());
861 return fileName.toAbsolutePath().toString();