Merge pull request #3839 from stianst/SOCIAL_LOGIN_TEST

KEYCLOAK-4265 Social login tests
This commit is contained in:
Stian Thorgersen 2017-02-09 10:15:17 +01:00 committed by GitHub
commit 8e16e5d953
6 changed files with 299 additions and 6 deletions

View file

@ -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`.

View file

@ -63,6 +63,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
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) {
firstNameInput.clear();
firstNameInput.sendKeys(firstName);
@ -141,6 +145,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
driver.navigate().to(getPath());
}
public void open(String realm) {
driver.navigate().to(getPath(realm));
}
public void backToApplication() {
backToApplicationLink.click();
}

View file

@ -41,12 +41,18 @@ public class LoginUpdateProfilePage extends AbstractPage {
private WebElement loginErrorMessage;
public void update(String firstName, String lastName, String email) {
if (firstName != null) {
firstNameInput.clear();
firstNameInput.sendKeys(firstName);
}
if (lastName != null) {
lastNameInput.clear();
lastNameInput.sendKeys(lastName);
}
if (email != null) {
emailInput.clear();
emailInput.sendKeys(email);
}
submitButton.click();
}

View file

@ -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;
}
}