Rework login in the selenium tests and add ability to start tests in the codenvy/codenvy (#6561)

6.19.x
Igor Ohrimenko 2017-10-05 15:02:27 +03:00 committed by GitHub
parent e002f1dc9e
commit be4dcd37db
16 changed files with 311 additions and 121 deletions

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.entrance;
import org.eclipse.che.selenium.core.user.TestUser;
/** @author Dmytro Nochevnov */
public interface Entrance {
/**
* Login to product.
*
* @param user user to login
*/
void login(TestUser user);
}

View File

@ -11,11 +11,12 @@
package org.eclipse.che.selenium.core.factory;
import org.eclipse.che.api.factory.shared.dto.FactoryDto;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.client.TestFactoryServiceClient;
import org.eclipse.che.selenium.core.client.TestWorkspaceServiceClient;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.provider.TestDashboardUrlProvider;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
import org.openqa.selenium.WebDriver;
/** @author Anatolii Bazko */
@ -25,8 +26,7 @@ public class TestFactory {
private final TestDashboardUrlProvider dashboardUrl;
private final TestFactoryServiceClient testFactoryServiceClient;
private final TestWorkspaceServiceClient workspaceServiceClient;
private final LoginPage loginPage;
private final Entrance entrance;
private final String factoryUrl;
public TestFactory(
@ -36,23 +36,21 @@ public class TestFactory {
TestDashboardUrlProvider dashboardUrl,
TestFactoryServiceClient factoryServiceClient,
TestWorkspaceServiceClient workspaceServiceClient,
LoginPage loginPage) {
Entrance entrance) {
this.factoryDto = factoryDto;
this.owner = owner;
this.factoryUrl = factoryUrl;
this.dashboardUrl = dashboardUrl;
this.testFactoryServiceClient = factoryServiceClient;
this.workspaceServiceClient = workspaceServiceClient;
this.loginPage = loginPage;
this.entrance = entrance;
}
/** Adds authentication token into the browser and opens factory url. */
public void authenticateAndOpen(WebDriver driver) throws Exception {
public void authenticateAndOpen(SeleniumWebDriver driver) throws Exception {
driver.get(dashboardUrl.get().toString());
if (loginPage.isOpened()) {
loginPage.login(owner.getName(), owner.getPassword());
}
entrance.login(owner);
driver.get(factoryUrl);
}

View File

@ -34,11 +34,11 @@ import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.selenium.core.client.TestFactoryServiceClient;
import org.eclipse.che.selenium.core.client.TestWorkspaceServiceClient;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.provider.TestApiEndpointUrlProvider;
import org.eclipse.che.selenium.core.provider.TestDashboardUrlProvider;
import org.eclipse.che.selenium.core.provider.TestIdeUrlProvider;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
/** @author Anatolii Bazko */
@Singleton
@ -51,7 +51,7 @@ public class TestFactoryInitializer {
@Inject private HttpJsonRequestFactory requestFactory;
@Inject private TestFactoryServiceClient testFactoryServiceClient;
@Inject private TestWorkspaceServiceClient workspaceServiceClient;
@Inject private LoginPage loginPage;
@Inject private Entrance entrance;
/**
* Initialize {@link TestFactory} base upon template.
@ -91,7 +91,7 @@ public class TestFactoryInitializer {
dashboardUrlProvider,
testFactoryServiceClient,
workspaceServiceClient,
loginPage);
entrance);
}
/** Builder for {@link TestFactory}. */
@ -111,7 +111,7 @@ public class TestFactoryInitializer {
dashboardUrlProvider,
testFactoryServiceClient,
workspaceServiceClient,
loginPage);
entrance);
}
@Override

View File

@ -10,12 +10,14 @@
*/
package org.eclipse.che.selenium.core.inject;
import static com.google.inject.Guice.createInjector;
import static java.lang.String.format;
import static java.util.Optional.ofNullable;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
@ -25,7 +27,9 @@ import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@ -33,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.validation.constraints.NotNull;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.constant.TestBrowser;
@ -64,6 +69,7 @@ import org.testng.TestException;
* invoked twice.
*
* @author Anatolii Bazko
* @author Dmitry Nochevnov
*/
public abstract class SeleniumTestHandler
implements ITestListener, ISuiteListener, IInvokedMethodListener {
@ -132,7 +138,7 @@ public abstract class SeleniumTestHandler
public void onStart(ISuite suite) {
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
Injector injector = createParentInjector();
Injector injector = createInjector(getParentModules());
injector.injectMembers(this);
suite.setParentInjector(injector);
@ -192,7 +198,10 @@ public abstract class SeleniumTestHandler
private void injectDependencies(ITestContext testContext, Object testInstance) throws Exception {
Injector injector = testContext.getSuite().getParentInjector();
Injector classInjector = injector.createChildInjector(new SeleniumClassModule());
List<Module> childModules = new ArrayList<>(getChildModules());
childModules.add(new SeleniumClassModule());
Injector classInjector = injector.createChildInjector(childModules);
classInjector.injectMembers(testInstance);
pageObjectsInjector.injectMembers(testInstance);
@ -333,6 +342,11 @@ public abstract class SeleniumTestHandler
}
}
/** Returns parent injector. */
public abstract Injector createParentInjector();
/** Returns list of parent modules */
@NotNull
public abstract List<Module> getParentModules();
/** Returns list of child modules */
@NotNull
public abstract List<Module> getChildModules();
}

View File

@ -13,6 +13,7 @@ package org.eclipse.che.selenium.core.user;
import static java.lang.String.format;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.ArrayList;
@ -47,12 +48,12 @@ public class TestUserImpl implements TestUser {
/** To instantiate user with generated email and password. */
@Inject
public TestUserImpl(
TestUserServiceClient userServiceClient,
Provider<TestUserServiceClient> userServiceClient,
TestAuthServiceClient authServiceClient,
TestWorkspaceServiceClientFactory wsServiceClientFactory)
throws Exception {
this(
userServiceClient,
userServiceClient.get(),
authServiceClient,
wsServiceClientFactory,
NameGenerator.generate("user", 6) + "@some.mail");
@ -90,7 +91,7 @@ public class TestUserImpl implements TestUser {
this.userServiceClient.create(name, email, password);
this.authToken = authServiceClient.login(name, password);
this.id = userServiceClient.findByEmail(email).getId();
LOG.info("User name='{}', password '{}', id='{}' has been created", name, password, id);
LOG.info("User name='{}', password='{}', id='{}' has been created", name, password, id);
this.workspaceServiceClient = wsServiceClientFactory.create(email, password);
}

View File

@ -12,6 +12,7 @@ package org.eclipse.che.selenium.core.workspace;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
@ -52,10 +53,10 @@ public class TestWorkspaceProviderImpl implements TestWorkspaceProvider {
public TestWorkspaceProviderImpl(
@Named("sys.threads") int threads,
@Named("workspace.default_memory_gb") int defaultMemoryGb,
TestUser defaultUser,
Provider<TestUser> defaultUser,
TestWorkspaceServiceClient testWorkspaceServiceClient,
TestWorkspaceServiceClientFactory testWorkspaceServiceClientFactory) {
this.defaultUser = defaultUser;
this.defaultUser = defaultUser.get();
this.defaultMemoryGb = defaultMemoryGb;
this.testWorkspaceServiceClient = testWorkspaceServiceClient;
this.testWorkspaceServiceClientFactory = testWorkspaceServiceClientFactory;

View File

@ -10,14 +10,24 @@
*/
package org.eclipse.che.selenium.core;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.che.selenium.core.inject.SeleniumTestHandler;
/** @author Anatolii Bazko */
public class CheSeleniumTesHandler extends SeleniumTestHandler {
@Override
public Injector createParentInjector() {
return Guice.createInjector(new CheSeleniumSuiteModule());
public List<Module> getParentModules() {
List<Module> modules = new ArrayList<>();
modules.add(new CheSeleniumSuiteModule());
return modules;
}
@Override
public List<Module> getChildModules() {
List<Module> modules = new ArrayList<>();
modules.add(new CheSeleniumWebDriverRelatedModule());
return modules;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import javax.inject.Named;
import org.eclipse.che.selenium.core.entrance.CookieEntrance;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.entrance.LoginPageEntrance;
import org.eclipse.che.selenium.pageobject.site.CheLoginPage;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
/**
* Module which is dedicated to deal with dependencies which are injecting SeleniumWebDriver.class
* itself.
*
* @author Dmytro Nochevnov
*/
public class CheSeleniumWebDriverRelatedModule extends AbstractModule {
private static final String CHE_MULTIUSER = "che.multiuser";
@Override
protected void configure() {
bind(LoginPage.class).to(CheLoginPage.class);
}
@Provides
public Entrance getEntrance(
@Named(CHE_MULTIUSER) boolean isMultiuser,
LoginPage loginPage,
SeleniumWebDriver seleniumWebDriver) {
if (isMultiuser) {
return new LoginPageEntrance(loginPage);
} else {
return new CookieEntrance(seleniumWebDriver);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.entrance;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.user.TestUser;
import org.openqa.selenium.Cookie;
/**
* Enter the product by adding "session-access-key=[auth_token]" to the cookie of web driver.
*
* @author Dmytro Nochevnov
*/
@Singleton
public class CookieEntrance implements Entrance {
private final SeleniumWebDriver seleniumWebDriver;
@Inject
public CookieEntrance(SeleniumWebDriver seleniumWebDriver) {
this.seleniumWebDriver = seleniumWebDriver;
}
/**
* Login to product by using cookies.
*
* @param user
*/
public void login(TestUser user) {
Cookie accessKey = new Cookie("session-access-key", user.getAuthToken());
seleniumWebDriver.manage().addCookie(accessKey);
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.core.entrance;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
/**
* Enter the product through the Login Page.
*
* @author Dmytro Nochevnov
*/
@Singleton
public class LoginPageEntrance implements Entrance {
private final LoginPage loginPage;
@Inject
public LoginPageEntrance(LoginPage loginPage) {
this.loginPage = loginPage;
}
/**
* Login to product.
*
* @param user
*/
public void login(TestUser user) {
if (loginPage.isOpened()) {
loginPage.login(user.getName(), user.getPassword());
}
}
}

View File

@ -10,58 +10,44 @@
*/
package org.eclipse.che.selenium.pageobject;
import static org.eclipse.che.selenium.core.constant.TestTimeoutsConstants.EXPECTED_MESS_IN_CONSOLE_SEC;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.net.URL;
import javax.annotation.PreDestroy;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.provider.TestIdeUrlProvider;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.workspace.TestWorkspace;
import org.eclipse.che.selenium.core.workspace.TestWorkspaceUrlResolver;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
/** @author Vitaliy Gulyy */
/**
* @author Vitaliy Gulyy
* @author Dmytro Nochevnov
*/
@Singleton
public class Ide {
private final SeleniumWebDriver seleniumWebDriver;
private final TestIdeUrlProvider testIdeUrlProvider;
private final TestWorkspaceUrlResolver testWorkspaceUrlResolver;
private final LoginPage loginPage;
private final Entrance entrance;
@Inject
public Ide(
SeleniumWebDriver seleniumWebDriver,
TestIdeUrlProvider testIdeUrlProvider,
TestWorkspaceUrlResolver testWorkspaceUrlResolver,
LoginPage loginPage) {
Entrance entrance) {
this.seleniumWebDriver = seleniumWebDriver;
this.testIdeUrlProvider = testIdeUrlProvider;
this.testWorkspaceUrlResolver = testWorkspaceUrlResolver;
this.loginPage = loginPage;
this.entrance = entrance;
}
@Deprecated
public WebDriver driver() {
public SeleniumWebDriver driver() {
return seleniumWebDriver;
}
public void open(TestWorkspace testWorkspace) throws Exception {
URL workspaceUrl = testWorkspaceUrlResolver.resolve(testWorkspace);
seleniumWebDriver.get(workspaceUrl.toString());
if (loginPage.isOpened()) {
loginPage.login(testWorkspace.getOwner().getName(), testWorkspace.getOwner().getPassword());
}
}
public void switchFromDashboard() {
new WebDriverWait(seleniumWebDriver, EXPECTED_MESS_IN_CONSOLE_SEC)
.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("ide-application-iframe")));
entrance.login(testWorkspace.getOwner());
}
@PreDestroy

View File

@ -22,11 +22,11 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.annotation.PreDestroy;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.entrance.Entrance;
import org.eclipse.che.selenium.core.provider.TestDashboardUrlProvider;
import org.eclipse.che.selenium.core.provider.TestIdeUrlProvider;
import org.eclipse.che.selenium.core.user.TestUser;
import org.eclipse.che.selenium.core.utils.WaitUtils;
import org.eclipse.che.selenium.pageobject.site.LoginPage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
@ -43,7 +43,7 @@ public class Dashboard {
private final TestIdeUrlProvider testIdeUrlProvider;
private final TestDashboardUrlProvider testDashboardUrlProvider;
private final LoginPage loginPage;
private final Entrance entrance;
@Inject
public Dashboard(
@ -51,12 +51,12 @@ public class Dashboard {
TestUser defaultUser,
TestIdeUrlProvider testIdeUrlProvider,
TestDashboardUrlProvider testDashboardUrlProvider,
LoginPage loginPage) {
Entrance entrance) {
this.seleniumWebDriver = seleniumWebDriver;
this.defaultUser = defaultUser;
this.testIdeUrlProvider = testIdeUrlProvider;
this.testDashboardUrlProvider = testDashboardUrlProvider;
this.loginPage = loginPage;
this.entrance = entrance;
PageFactory.initElements(seleniumWebDriver, this);
}
@ -194,9 +194,7 @@ public class Dashboard {
/** Open dashboard as default uses */
public void open() {
seleniumWebDriver.get(testDashboardUrlProvider.get().toString());
if (loginPage.isOpened()) {
loginPage.login(defaultUser.getName(), defaultUser.getPassword());
}
entrance.login(defaultUser);
}
public WebDriver driver() {

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.selenium.pageobject.site;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.constant.TestTimeoutsConstants;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
/** @author Dmytro Nochevnov */
@Singleton
public class CheLoginPage implements LoginPage {
private final SeleniumWebDriver seleniumWebDriver;
private final WebDriverWait webDriverWait;
@FindBy(name = "username")
private WebElement usernameInput;
@FindBy(name = "password")
private WebElement passwordInput;
@FindBy(name = "login")
private WebElement loginButton;
@Inject
public CheLoginPage(SeleniumWebDriver seleniumWebDriver) {
this.seleniumWebDriver = seleniumWebDriver;
PageFactory.initElements(seleniumWebDriver, this);
webDriverWait =
new WebDriverWait(seleniumWebDriver, TestTimeoutsConstants.REDRAW_UI_ELEMENTS_TIMEOUT_SEC);
}
public void login(String username, String password) {
waitOnOpen();
usernameInput.clear();
usernameInput.sendKeys(username);
passwordInput.clear();
passwordInput.sendKeys(password);
loginButton.click();
waitOnClose();
}
public void waitOnOpen() {
webDriverWait.until(ExpectedConditions.visibilityOf(loginButton));
}
public void waitOnClose() {
webDriverWait.until(
ExpectedConditions.invisibilityOfAllElements(ImmutableList.of(loginButton)));
}
public boolean isOpened() {
try {
waitOnOpen();
} catch (TimeoutException e) {
return false;
}
return true;
}
}

View File

@ -10,69 +10,16 @@
*/
package org.eclipse.che.selenium.pageobject.site;
import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.selenium.core.SeleniumWebDriver;
import org.eclipse.che.selenium.core.constant.TestTimeoutsConstants;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
/** @author Dmytro Nochevnov */
@Singleton
public class LoginPage {
public interface LoginPage {
private final SeleniumWebDriver seleniumWebDriver;
/**
* Login Page of product.
*
* @param username login username
* @param password login password
*/
void login(String username, String password);
private final WebDriverWait loadPageTimeout;
@FindBy(name = "username")
private WebElement usernameInput;
@FindBy(name = "password")
private WebElement passwordInput;
@FindBy(name = "login")
private WebElement loginButton;
@Inject
public LoginPage(SeleniumWebDriver seleniumWebDriver) {
this.seleniumWebDriver = seleniumWebDriver;
PageFactory.initElements(seleniumWebDriver, this);
loadPageTimeout =
new WebDriverWait(seleniumWebDriver, TestTimeoutsConstants.ATTACHING_ELEM_TO_DOM_SEC);
}
public void login(String username, String password) {
waitOnOpen();
usernameInput.clear();
usernameInput.sendKeys(username);
passwordInput.clear();
passwordInput.sendKeys(password);
loginButton.click();
waitOnClose();
}
public void waitOnOpen() {
loadPageTimeout.until(ExpectedConditions.visibilityOf(loginButton));
}
public void waitOnClose() {
loadPageTimeout.until(
ExpectedConditions.invisibilityOfAllElements(ImmutableList.of(loginButton)));
}
public boolean isOpened() {
try {
waitOnOpen();
} catch (TimeoutException e) {
return false;
}
return true;
}
boolean isOpened();
}

View File

@ -28,8 +28,8 @@ google.password=
# Define configuration for che default test user.
# For che single user assembly, the default values will be enough.
# For che multiuser assembly, user must be already created on identity provider service.
che.test_user.email=che@eclipse.org
che.test_user.password=secret
che.test_user.email=
che.test_user.password=
# Define configuration for admin test user.
# Note that admin user needs only for multiuser assembly and