KEYCLOAK-3616 Add integration tests for Node.js adapter

This commit is contained in:
Vaclav Muzikar 2016-09-27 10:32:35 +02:00
parent fc6d6ff7f7
commit ee2daeb364
7 changed files with 324 additions and 1 deletions

View file

@ -71,6 +71,7 @@ public final class WaitUtils {
}
public static void pause(long millis) {
log.info("Wait: " + millis + "ms");
try {
Thread.sleep(millis);
} catch (InterruptedException ex) {

View file

@ -199,7 +199,6 @@ public class SecurityDefensesTest extends AbstractRealmTest {
wait *= 1000;
log.info("Wait: " + wait);
pause(wait);
if (finalLogin) {

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.keycloak.testsuite</groupId>
<artifactId>integration-arquillian-tests-other</artifactId>
<version>2.2.0-SNAPSHOT</version>
</parent>
<artifactId>integration-arquillian-tests-nodejs-adapter</artifactId>
<name>Node.js adapter tests</name>
<properties>
<testsuite.adapter.nodejs.example.url>http://localhost:3000/</testsuite.adapter.nodejs.example.url>
<auth.server.port.offset>0</auth.server.port.offset>
<auth.server.http.port>8080</auth.server.http.port>
<auth.server.https.port>8443</auth.server.https.port>
<auth.server.management.port>9990</auth.server.management.port>
<auth.server.management.port.jmx>9999</auth.server.management.port.jmx>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<testsuite.adapter.nodejs.example.url>${testsuite.adapter.nodejs.example.url}</testsuite.adapter.nodejs.example.url>
</systemProperties>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View file

@ -0,0 +1,34 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.adapter.nodejs.page;
import org.keycloak.testsuite.page.AbstractPage;
import javax.ws.rs.core.UriBuilder;
/**
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
public abstract class AbstractNodejsExamplePage extends AbstractPage {
private static final String EXAMPLE_URL_PROPERY_NAME = "testsuite.adapter.nodejs.example.url";
@Override
public UriBuilder createUriBuilder() {
return UriBuilder.fromUri(System.getProperty(EXAMPLE_URL_PROPERY_NAME));
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.adapter.nodejs.page;
import org.keycloak.testsuite.util.URLUtils;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import javax.ws.rs.core.UriBuilder;
/**
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
public class NodejsExamplePage extends AbstractNodejsExamplePage {
@FindBy(xpath = "//div[@class='nav']//a[text()='Login']")
private WebElement loginButton;
@FindBy(xpath = "//div[@class='nav']//a[text()='Logout']")
private WebElement logoutButton;
@FindBy(id = "output")
private WebElement outputBox;
public void clickLogin() {
loginButton.click();
}
public void clickLogout() {
logoutButton.click();
}
public String getOutput() {
return outputBox.getText();
}
public boolean isOnLoginSecuredPage() {
UriBuilder uriBuilder = createUriBuilder().path("login");
return URLUtils.currentUrlEqual(driver, uriBuilder.build().toASCIIString());
}
@Override
public boolean isCurrent() {
return URLUtils.currentUrlStartWith(driver, toString());
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.adapter.nodejs;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractAuthTest;
import org.keycloak.testsuite.adapter.nodejs.page.NodejsExamplePage;
import java.io.File;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.util.IOUtil.loadRealm;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
import static org.keycloak.testsuite.util.WaitUtils.pause;
/**
* This test class expects following:
* <ul>
* <li>The {@value #EXAMPLE_REALM_PROPERTY_NAME} System Property to be set and pointing to a realm configuration file
* of the example app from keycloak-nodejs-connect project</li>
* <li>The stated example app to be running</li>
* </ul>
*
* @author Vaclav Muzikar <vmuzikar@redhat.com>
*/
public class NodejsAdapterTest extends AbstractAuthTest {
private static final String EXAMPLE_REALM_PROPERTY_NAME = "testsuite.adapter.nodejs.example.realm";
private static RealmRepresentation exampleRealm;
private static final String USER = "user";
private static final String PASSWORD = "password";
@Page
private NodejsExamplePage nodejsExamplePage;
@BeforeClass
public static void beforeNodejsAdapterTestClass() {
String exampleRealmPath = System.getProperty(EXAMPLE_REALM_PROPERTY_NAME);
if (exampleRealmPath == null) {
throw new IllegalStateException(EXAMPLE_REALM_PROPERTY_NAME + " property must be set");
}
exampleRealm = loadRealm(new File(exampleRealmPath));
}
@Before
public void beforeNodejsAdapterTest() {
nodejsExamplePage.navigateTo();
driver.manage().deleteAllCookies();
}
@Override
public void setDefaultPageUriParameters() {
super.setDefaultPageUriParameters();
testRealmPage.setAuthRealm(exampleRealm.getRealm());
}
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
testRealms.add(exampleRealm);
}
@Test
public void simpleLoginTest() {
nodejsExamplePage.navigateTo();
assertCurrentUrlEquals(nodejsExamplePage);
nodejsExamplePage.clickLogin();
assertCurrentUrlStartsWithLoginUrlOf(testRealmLoginPage);
testRealmLoginPage.form().login(USER, PASSWORD);
assertTrue("Should be redirected back to the secured page after the login", nodejsExamplePage.isOnLoginSecuredPage());
String output = nodejsExamplePage.getOutput();
assertFalse("Output should not be empty", output.isEmpty());
nodejsExamplePage.clickLogin();
assertTrue("Should be already logged in", nodejsExamplePage.isOnLoginSecuredPage());
assertEquals("Authentication responses should be the same", output, nodejsExamplePage.getOutput());
nodejsExamplePage.clickLogout();
assertCurrentUrlEquals(nodejsExamplePage);
nodejsExamplePage.clickLogin();
assertCurrentUrlStartsWithLoginUrlOf(testRealmLoginPage);
}
@Test
public void timeoutsTest() {
// in seconds
final int ssoTimeout = 15;
final int tokenTimeout = 10;
// change the realm's timeouts
RealmRepresentation realmUpdate = new RealmRepresentation();
realmUpdate.setSsoSessionIdleTimeout(ssoTimeout);
realmUpdate.setAccessTokenLifespan(tokenTimeout);
adminClient.realm(exampleRealm.getRealm()).update(realmUpdate);
// test access token lifespan
nodejsExamplePage.clickLogin();
testRealmLoginPage.form().login(USER, PASSWORD);
assertTrue("Should be logged in", nodejsExamplePage.isOnLoginSecuredPage());
String output = nodejsExamplePage.getOutput();
pause(tokenTimeout * 1000);
nodejsExamplePage.clickLogin();
assertTrue("Should be still logged in", nodejsExamplePage.isOnLoginSecuredPage());
assertNotEquals("Authentication responses should be different", output, nodejsExamplePage.getOutput()); // token should be refreshed
// test SSO timeout
pause(ssoTimeout * 1000);
nodejsExamplePage.clickLogin();
assertCurrentUrlStartsWithLoginUrlOf(testRealmLoginPage); // there should be an attempt for token refresh
// but SSO session should be already expired
}
// KEYCLOAK-3284
@Test
@Ignore // to be enabled when KEYCLOAK-3284 is fixed
public void sessionTest() {
nodejsExamplePage.clickLogin();
testRealmLoginPage.form().login(USER, PASSWORD);
assertTrue("Should be logged in", nodejsExamplePage.isOnLoginSecuredPage());
testRealmAccountPage.navigateTo();
assertCurrentUrlEquals(testRealmAccountPage); // should be already logged in
testRealmAccountPage.logOut();
assertCurrentUrlStartsWithLoginUrlOf(testRealmLoginPage);
nodejsExamplePage.navigateTo();
nodejsExamplePage.clickLogin();
assertCurrentUrlStartsWithLoginUrlOf(testRealmLoginPage); // should be logged out
}
}

View file

@ -142,6 +142,12 @@
<module>jpa-performance</module>
</modules>
</profile>
<profile>
<id>nodejs-adapter-tests</id>
<modules>
<module>nodejs_adapter</module>
</modules>
</profile>
</profiles>
</project>