Merge pull request #3839 from stianst/SOCIAL_LOGIN_TEST
KEYCLOAK-4265 Social login tests
This commit is contained in:
commit
8e16e5d953
6 changed files with 299 additions and 6 deletions
|
@ -159,5 +159,52 @@ mvn -f testsuite/integration-arquillian/pom.xml \
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|
||||||
|
## Social Login
|
||||||
|
The social login tests require setup of all social networks including an example social user. These details can't be
|
||||||
|
shared as it would result in the clients and users eventually being blocked. By default these tests are skipped.
|
||||||
|
|
||||||
|
To run the full test you need to configure clients in Google, Facebook, GitHub, Twitter, LinkedIn, Microsoft and
|
||||||
|
StackOverflow. See the server administration guide for details on how to do that. Further, you also need to create a
|
||||||
|
sample user that can login to the social network.
|
||||||
|
|
||||||
|
The details should be added to a standard properties file. For some properties you can use shared common properties and
|
||||||
|
override when needed. Or you can specify these for all providers. All providers require at least clientId and
|
||||||
|
clientSecret (StackOverflow also requires clientKey).
|
||||||
|
|
||||||
|
An example social.properties file looks like:
|
||||||
|
|
||||||
|
common.username=sampleuser@example.org
|
||||||
|
common.password=commonpassword
|
||||||
|
common.profile.firstName=Foo
|
||||||
|
common.profile.lastName=Bar
|
||||||
|
common.profile.email=sampleuser@example.org
|
||||||
|
|
||||||
|
google.clientId=asdfasdfasdfasdfsadf
|
||||||
|
google.clientSecret=zxcvzxcvzxcvzxcv
|
||||||
|
|
||||||
|
facebook.clientId=asdfasdfasdfasdfsadf
|
||||||
|
facebook.clientSecret=zxcvzxcvzxcvzxcv
|
||||||
|
facebook.profile.lastName=Test
|
||||||
|
|
||||||
|
In the example above the common username, password and profile are shared for all providers, but Facebook has a
|
||||||
|
different last name.
|
||||||
|
|
||||||
|
Some providers actively block bots so you need to use a proper browser to test. Either Firefox or Chrome should work.
|
||||||
|
|
||||||
|
To run the tests run:
|
||||||
|
|
||||||
|
mvn -f testsuite/integration-arquillian/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Dtest=SocialLoginTest \
|
||||||
|
-Dbrowser=chrome \
|
||||||
|
-Dsocial.config=/path/to/social.properties
|
||||||
|
|
||||||
|
|
||||||
|
## Different Browsers
|
||||||
|
|
||||||
|
To run with Chrome add `-Dbrowser=chrome`. Depending on the Chrome version you have you may need to download the latest
|
||||||
|
chromedriver from https://sites.google.com/a/chromium.org/chromedriver/downloads and point to it with
|
||||||
|
`-Dwebdriver.chrome.driver=/path/to/chromedriver`.
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -63,6 +63,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
|
||||||
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString();
|
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPath(String realm) {
|
||||||
|
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build(realm).toString();
|
||||||
|
}
|
||||||
|
|
||||||
public void updateProfile(String firstName, String lastName, String email) {
|
public void updateProfile(String firstName, String lastName, String email) {
|
||||||
firstNameInput.clear();
|
firstNameInput.clear();
|
||||||
firstNameInput.sendKeys(firstName);
|
firstNameInput.sendKeys(firstName);
|
||||||
|
@ -141,6 +145,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
|
||||||
driver.navigate().to(getPath());
|
driver.navigate().to(getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void open(String realm) {
|
||||||
|
driver.navigate().to(getPath(realm));
|
||||||
|
}
|
||||||
|
|
||||||
public void backToApplication() {
|
public void backToApplication() {
|
||||||
backToApplicationLink.click();
|
backToApplicationLink.click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,18 @@ public class LoginUpdateProfilePage extends AbstractPage {
|
||||||
private WebElement loginErrorMessage;
|
private WebElement loginErrorMessage;
|
||||||
|
|
||||||
public void update(String firstName, String lastName, String email) {
|
public void update(String firstName, String lastName, String email) {
|
||||||
firstNameInput.clear();
|
if (firstName != null) {
|
||||||
firstNameInput.sendKeys(firstName);
|
firstNameInput.clear();
|
||||||
lastNameInput.clear();
|
firstNameInput.sendKeys(firstName);
|
||||||
lastNameInput.sendKeys(lastName);
|
}
|
||||||
emailInput.clear();
|
if (lastName != null) {
|
||||||
emailInput.sendKeys(email);
|
lastNameInput.clear();
|
||||||
|
lastNameInput.sendKeys(lastName);
|
||||||
|
}
|
||||||
|
if (email != null) {
|
||||||
|
emailInput.clear();
|
||||||
|
emailInput.sendKeys(email);
|
||||||
|
}
|
||||||
submitButton.click();
|
submitButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
package org.keycloak.testsuite.broker;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.graphene.Graphene;
|
||||||
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import org.jboss.arquillian.graphene.wait.WebDriverWait;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
|
import org.keycloak.testsuite.cli.exec.ExecutionException;
|
||||||
|
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
|
||||||
|
import org.keycloak.testsuite.pages.LoginPage;
|
||||||
|
import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
|
||||||
|
import org.keycloak.testsuite.util.IdentityProviderBuilder;
|
||||||
|
import org.keycloak.testsuite.util.RealmBuilder;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by st on 19.01.17.
|
||||||
|
*/
|
||||||
|
public class SocialLoginTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
|
public static final String SOCIAL_CONFIG = "social.config";
|
||||||
|
|
||||||
|
private static Properties config = new Properties();
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public AccountUpdateProfilePage account;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public LoginPage loginPage;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public LoginUpdateProfilePage updateProfilePage;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void loadConfig() throws Exception {
|
||||||
|
assumeTrue(System.getProperties().containsKey(SOCIAL_CONFIG));
|
||||||
|
|
||||||
|
config.load(new FileInputStream(System.getProperty(SOCIAL_CONFIG)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
|
RealmRepresentation rep = RealmBuilder.create().name("social").build();
|
||||||
|
List<IdentityProviderRepresentation> idps = new LinkedList<>();
|
||||||
|
rep.setIdentityProviders(idps);
|
||||||
|
|
||||||
|
idps.add(buildIdp("google"));
|
||||||
|
idps.add(buildIdp("facebook"));
|
||||||
|
idps.add(buildIdp("github"));
|
||||||
|
idps.add(buildIdp("twitter"));
|
||||||
|
idps.add(buildIdp("linkedin"));
|
||||||
|
idps.add(buildIdp("microsoft"));
|
||||||
|
idps.add(buildIdp("stackoverflow"));
|
||||||
|
|
||||||
|
testRealms.add(rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void googleLogin() throws InterruptedException {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("google");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("Email")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("Email")).sendKeys(config.getProperty("google.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("next")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("Passwd")).sendKeys(config.getProperty("google.password", config.getProperty("common.password")));
|
||||||
|
driver.findElement(By.id("signIn")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.elementToBeClickable(By.id("submit_approve_access")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("submit_approve_access")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("google.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("google.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("google.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void faceBookLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("facebook");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("email")));
|
||||||
|
driver.findElement(By.id("email")).sendKeys(config.getProperty("facebook.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("pass")).sendKeys(config.getProperty("facebook.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("loginbutton")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("facebook.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("facebook.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("facebook.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void githubLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("github");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("login_field")));
|
||||||
|
driver.findElement(By.id("login_field")).sendKeys(config.getProperty("github.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("password")).sendKeys(config.getProperty("github.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.name("commit")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("github.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("github.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("github.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twitterLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("twitter");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("username_or_email")));
|
||||||
|
driver.findElement(By.id("username_or_email")).sendKeys(config.getProperty("twitter.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("password")).sendKeys(config.getProperty("twitter.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("allow")).click();
|
||||||
|
|
||||||
|
assertTrue(updateProfilePage.isCurrent());
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("twitter.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals("", updateProfilePage.getEmail());
|
||||||
|
|
||||||
|
updateProfilePage.update(null, null, "keycloakey@gmail.com");
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("twitter.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void linkedinLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("linkedin");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("session_key-oauth2SAuthorizeForm")));
|
||||||
|
driver.findElement(By.id("session_key-oauth2SAuthorizeForm")).sendKeys(config.getProperty("linkedin.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("session_password-oauth2SAuthorizeForm")).sendKeys(config.getProperty("linkedin.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.name("authorize")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void microsoftLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("microsoft");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("loginfmt")));
|
||||||
|
driver.findElement(By.name("loginfmt")).sendKeys(config.getProperty("microsoft.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.xpath("//input[@value='Next']")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("passwd")));
|
||||||
|
driver.findElement(By.name("passwd")).sendKeys(config.getProperty("microsoft.password", config.getProperty("common.password")));
|
||||||
|
driver.findElement(By.xpath("//input[@value='Sign in']")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void stackoverflowLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("stackoverflow");
|
||||||
|
|
||||||
|
Graphene.waitModel().until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[@title='log in with Stack_Exchange']")));
|
||||||
|
driver.findElement(By.xpath("//a[@title='log in with Stack_Exchange']")).click();
|
||||||
|
|
||||||
|
driver.switchTo().frame(driver.findElement(By.id("affiliate-signin-iframe")));
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("email")));
|
||||||
|
driver.findElement(By.name("email")).sendKeys(config.getProperty("stackoverflow.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.name("password")).sendKeys(config.getProperty("stackoverflow.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.xpath("//input[@value='Sign In']")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.firstName", config.getProperty("common.profile.firstName")), updateProfilePage.getFirstName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.lastName", config.getProperty("common.profile.lastName")), updateProfilePage.getLastName());
|
||||||
|
assertEquals("", updateProfilePage.getEmail());
|
||||||
|
|
||||||
|
updateProfilePage.update(null, null, "keycloakey@gmail.com");
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdentityProviderRepresentation buildIdp(String id) {
|
||||||
|
IdentityProviderRepresentation idp = IdentityProviderBuilder.create().alias(id).providerId(id).build();
|
||||||
|
idp.setEnabled(true);
|
||||||
|
idp.getConfig().put("clientId", config.getProperty(id + ".clientId"));
|
||||||
|
idp.getConfig().put("clientSecret", config.getProperty(id + ".clientSecret"));
|
||||||
|
if (id.equals("stackoverflow")) {
|
||||||
|
idp.getConfig().put("key", config.getProperty(id + ".clientKey"));
|
||||||
|
}
|
||||||
|
return idp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
Loading…
Reference in a new issue