mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
merge with branch 1.x
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.filter;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AdminSecurityFilter}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
public class AdminSecurityFilterTest {
|
||||
|
||||
private AdminSecurityFilter securityFilter;
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
/**
|
||||
* Prepare object under test and mocks.
|
||||
*/
|
||||
@Before
|
||||
public void setUp(){
|
||||
this.securityFilter = new AdminSecurityFilter(new ScmConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AdminSecurityFilter#hasPermission(org.apache.shiro.subject.Subject)} as administrator.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(username = "dent", password = "secret")
|
||||
public void testHasPermissionAsAdministrator() {
|
||||
assertTrue(securityFilter.hasPermission(SecurityUtils.getSubject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AdminSecurityFilter#hasPermission(org.apache.shiro.subject.Subject)} as user.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void testHasPermissionAsUser() {
|
||||
assertFalse(securityFilter.hasPermission(SecurityUtils.getSubject()));
|
||||
}
|
||||
|
||||
}
|
||||
130
scm-webapp/src/test/java/sonia/scm/filter/MDCFilterTest.java
Normal file
130
scm-webapp/src/test/java/sonia/scm/filter/MDCFilterTest.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.filter;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.slf4j.MDC;
|
||||
import sonia.scm.AbstractTestBase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MDCFilter}.
|
||||
*
|
||||
* @author Sebastian Sdorra <sebastian.sdorra@gmail.com>
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MDCFilterTest extends AbstractTestBase {
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
private final MDCFilter filter = new MDCFilter();
|
||||
|
||||
/**
|
||||
* Tests {@link MDCFilter#doFilter(HttpServletRequest, HttpServletResponse, FilterChain)}.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
username = "trillian",
|
||||
password = "secret",
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testDoFilter() throws IOException, ServletException
|
||||
{
|
||||
when(request.getRequestURI()).thenReturn("api/v1/repositories");
|
||||
when(request.getRemoteAddr()).thenReturn("127.0.0.1");
|
||||
when(request.getRemoteHost()).thenReturn("localhost");
|
||||
when(request.getMethod()).thenReturn("GET");
|
||||
|
||||
MDCCapturingFilterChain chain = new MDCCapturingFilterChain();
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
assertNotNull(chain.ctx);
|
||||
assertEquals("trillian", chain.ctx.get(MDCFilter.MDC_USERNAME));
|
||||
assertEquals("api/v1/repositories", chain.ctx.get(MDCFilter.MDC_REQUEST_URI));
|
||||
assertEquals("127.0.0.1", chain.ctx.get(MDCFilter.MDC_CLIEN_IP));
|
||||
assertEquals("localhost", chain.ctx.get(MDCFilter.MDC_CLIEN_HOST));
|
||||
assertEquals("GET", chain.ctx.get(MDCFilter.MDC_REQUEST_METHOD));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link MDCFilter#doFilter(HttpServletRequest, HttpServletResponse, FilterChain)} as anonymous user.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware
|
||||
public void testDoFilterAsAnonymous() throws IOException, ServletException {
|
||||
MDCCapturingFilterChain chain = new MDCCapturingFilterChain();
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
assertNotNull(chain.ctx);
|
||||
assertEquals("anonymous", chain.ctx.get(MDCFilter.MDC_USERNAME));
|
||||
}
|
||||
|
||||
private static class MDCCapturingFilterChain implements FilterChain {
|
||||
|
||||
private Map<String, String> ctx;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
this.ctx = MDC.getCopyOfContextMap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.filter;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserTestData;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SecurityFilter}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
public class SecurityFilterTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<HttpServletRequest> requestCaptor;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<HttpServletResponse> responseCaptor;
|
||||
|
||||
@Mock
|
||||
private FilterChain chain;
|
||||
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
private SecurityFilter securityFilter;
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
/**
|
||||
* Prepare object under test and mocks.
|
||||
*/
|
||||
@Before
|
||||
public void setUp(){
|
||||
this.configuration = new ScmConfiguration();
|
||||
this.securityFilter = new SecurityFilter(configuration);
|
||||
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter on authentication endpoint.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoOnAuthenticationUrl() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api/rest/authentication");
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
verify(request, never()).setAttribute(Mockito.anyString(), Mockito.any());
|
||||
verify(chain).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter without prior authentication.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testAnonymous() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter without prior authentication and enabled anonymous access.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testAnonymousWithAccessEnabled() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
configuration.setAnonymousAccessEnabled(true);
|
||||
|
||||
// execute
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
|
||||
// verify and capture
|
||||
verify(request).setAttribute(SecurityFilter.ATTRIBUTE_REMOTE_USER, SCMContext.USER_ANONYMOUS);
|
||||
verify(chain).doFilter(requestCaptor.capture(), responseCaptor.capture());
|
||||
|
||||
// assert
|
||||
HttpServletRequest captured = requestCaptor.getValue();
|
||||
assertEquals(SCMContext.USER_ANONYMOUS, captured.getRemoteUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter with prior authentication.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticated() throws IOException, ServletException {
|
||||
authenticateUser(UserTestData.createTrillian());
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
|
||||
// execute
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
|
||||
// verify and capture
|
||||
verify(request).setAttribute(SecurityFilter.ATTRIBUTE_REMOTE_USER, "trillian");
|
||||
verify(chain).doFilter(requestCaptor.capture(), responseCaptor.capture());
|
||||
|
||||
// assert
|
||||
HttpServletRequest captured = requestCaptor.getValue();
|
||||
assertEquals("trillian", captured.getRemoteUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter without permissions.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testForbidden() throws IOException, ServletException {
|
||||
authenticateUser(UserTestData.createTrillian());
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
|
||||
// execute
|
||||
securityFilter = new AccessForbiddenSecurityFilter(configuration);
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
|
||||
// assert
|
||||
verify(response).sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter unauthenticated and without permissions.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testUnauthorized() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
|
||||
// execute
|
||||
securityFilter = new AccessForbiddenSecurityFilter(configuration);
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
|
||||
// assert
|
||||
verify(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
private void authenticateUser(User user) {
|
||||
SimplePrincipalCollection spc = new SimplePrincipalCollection();
|
||||
spc.add(user.getName(), "unit-test");
|
||||
spc.add(user, "unit-test");
|
||||
|
||||
Subject subject = new Subject.Builder()
|
||||
.authenticated(true)
|
||||
.principals(spc)
|
||||
.buildSubject();
|
||||
|
||||
shiro.setSubject(subject);
|
||||
}
|
||||
|
||||
private static class AccessForbiddenSecurityFilter extends SecurityFilter {
|
||||
|
||||
private AccessForbiddenSecurityFilter(ScmConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(Subject subject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -286,7 +286,7 @@ public class AnonymousAccessITCase
|
||||
File directory = temporaryFolder.newFolder();
|
||||
RepositoryClient client = null;
|
||||
|
||||
String url = repository.createUrl(URL);
|
||||
String url = repository.createUrl(BASE_URL);
|
||||
|
||||
if ((username != null) && (password != null))
|
||||
{
|
||||
|
||||
@@ -37,7 +37,6 @@ package sonia.scm.it;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -264,7 +263,7 @@ public class ChangesetViewerITCase extends AbstractAdminITCaseBase
|
||||
throws RepositoryClientException
|
||||
{
|
||||
return RepositoryClientFactory.createClient(repositoryType, localDirectory,
|
||||
repository.createUrl(URL), IntegrationTestUtil.ADMIN_USERNAME,
|
||||
repository.createUrl(BASE_URL), IntegrationTestUtil.ADMIN_USERNAME,
|
||||
IntegrationTestUtil.ADMIN_PASSWORD);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,12 @@ public final class IntegrationTestUtil
|
||||
|
||||
/** Field description */
|
||||
public static final String ADMIN_USERNAME = "scmadmin";
|
||||
|
||||
public static final String URL = "http://localhost:8081/scm";
|
||||
|
||||
/** Field description */
|
||||
public static final String BASE_URL = "http://localhost:8081/scm/api/rest/";
|
||||
/** scm-manager base url */
|
||||
public static final String BASE_URL = "http://localhost:8081/scm/";
|
||||
|
||||
/** scm-manager base url for the rest api */
|
||||
public static final String REST_BASE_URL = BASE_URL.concat("api/rest/");
|
||||
|
||||
/** Field description */
|
||||
public static final String EXTENSION = ".xml";
|
||||
@@ -256,7 +257,7 @@ public final class IntegrationTestUtil
|
||||
*/
|
||||
public static String createResourceUrl(String url)
|
||||
{
|
||||
return BASE_URL.concat(url).concat(EXTENSION);
|
||||
return REST_BASE_URL.concat(url).concat(EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
211
scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java
Normal file
211
scm-webapp/src/test/java/sonia/scm/it/RepositoryHookITCase.java
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.it;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.Files;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import sonia.scm.debug.DebugHookData;
|
||||
import static sonia.scm.it.IntegrationTestUtil.createResource;
|
||||
import static sonia.scm.it.RepositoryITUtil.createRepository;
|
||||
import static sonia.scm.it.RepositoryITUtil.deleteRepository;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.repository.client.api.RepositoryClient;
|
||||
import sonia.scm.repository.client.api.RepositoryClientFactory;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
/**
|
||||
* Integration tests for repository hooks.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class RepositoryHookITCase extends AbstractAdminITCaseBase
|
||||
{
|
||||
|
||||
private static final long WAIT_TIME = 125;
|
||||
|
||||
private static final RepositoryClientFactory REPOSITORY_CLIENT_FACTORY = new RepositoryClientFactory();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
private final String repositoryType;
|
||||
private Repository repository;
|
||||
private File workingCopy;
|
||||
private RepositoryClient repositoryClient;
|
||||
|
||||
/**
|
||||
* Constructs a new instance with a repository type.
|
||||
*
|
||||
* @param repositoryType repository type
|
||||
*/
|
||||
public RepositoryHookITCase(String repositoryType)
|
||||
{
|
||||
this.repositoryType = repositoryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test repository.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Before
|
||||
public void setUpTestRepository() throws IOException
|
||||
{
|
||||
repository = RepositoryTestData.createHeartOfGold(repositoryType);
|
||||
repository = createRepository(client, repository);
|
||||
workingCopy = tempFolder.newFolder();
|
||||
repositoryClient = createRepositoryClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the tests repository.
|
||||
*/
|
||||
@After
|
||||
public void removeTestRepository()
|
||||
{
|
||||
deleteRepository(client, repository.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the debug service has received the commit.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleHook() throws IOException, InterruptedException
|
||||
{
|
||||
// push commit
|
||||
Files.write("a", new File(workingCopy, "a.txt"), Charsets.UTF_8);
|
||||
repositoryClient.getAddCommand().add("a.txt");
|
||||
Changeset changeset = repositoryClient.getCommitCommand().commit(
|
||||
new Person("scmadmin", "scmadmin@scm-manager.org"), "added a"
|
||||
);
|
||||
repositoryClient.getPushCommand().push();
|
||||
|
||||
// wait some time, because the debug hook is asnychron
|
||||
Thread.sleep(WAIT_TIME);
|
||||
|
||||
// check debug servlet for pushed commit
|
||||
WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last");
|
||||
DebugHookData data = wr.get(DebugHookData.class);
|
||||
assertNotNull(data);
|
||||
assertThat(data.getChangesets(), contains(changeset.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the debug service receives only new commits.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Test
|
||||
public void testOnlyNewCommit() throws IOException, InterruptedException
|
||||
{
|
||||
// push commit
|
||||
Files.write("a", new File(workingCopy, "a.txt"), Charsets.UTF_8);
|
||||
repositoryClient.getAddCommand().add("a.txt");
|
||||
Changeset a = repositoryClient.getCommitCommand().commit(
|
||||
new Person("scmadmin", "scmadmin@scm-manager.org"), "added a"
|
||||
);
|
||||
repositoryClient.getPushCommand().push();
|
||||
|
||||
// create branch, commit and push again
|
||||
repositoryClient.getBranchCommand().branch("feature/added-b");
|
||||
Files.write("b", new File(workingCopy, "b.txt"), Charsets.UTF_8);
|
||||
repositoryClient.getAddCommand().add("a.txt");
|
||||
Changeset b = repositoryClient.getCommitCommand().commit(
|
||||
new Person("scmadmin", "scmadmin@scm-manager.org"), "added b"
|
||||
);
|
||||
repositoryClient.getPushCommand().push();
|
||||
|
||||
// wait some time, because the debug hook is asnychron
|
||||
Thread.sleep(WAIT_TIME);
|
||||
|
||||
// check debug servlet that only one commit is present
|
||||
WebResource wr = createResource(client, "debug/" + repository.getId() + "/post-receive/last");
|
||||
DebugHookData data = wr.get(DebugHookData.class);
|
||||
assertNotNull(data);
|
||||
assertThat(data.getChangesets(), allOf(
|
||||
contains(b.getId()),
|
||||
not(
|
||||
contains(a.getId())
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
private RepositoryClient createRepositoryClient() throws IOException
|
||||
{
|
||||
return REPOSITORY_CLIENT_FACTORY.create(repositoryType,
|
||||
IntegrationTestUtil.BASE_URL + repositoryType + "/" + repository.getName(),
|
||||
IntegrationTestUtil.ADMIN_USERNAME, IntegrationTestUtil.ADMIN_PASSWORD, workingCopy
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns repository types a test parameter.
|
||||
*
|
||||
* @return repository types test parameter
|
||||
*/
|
||||
@Parameters
|
||||
public static Collection<String[]> createParameters()
|
||||
{
|
||||
Collection<String[]> params = Lists.newArrayList();
|
||||
params.add(new String[] { "git" });
|
||||
// params.add(new String[] { "svn" });
|
||||
if (IOUtil.search("hg") != null)
|
||||
{
|
||||
params.add(new String[] { "hg" });
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,8 @@ package sonia.scm.it;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.After;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -45,23 +46,23 @@ import sonia.scm.repository.Permission;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static sonia.scm.it.IntegrationTestUtil.*;
|
||||
import static sonia.scm.it.RepositoryITUtil.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import com.sun.jersey.api.client.Client;
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.GenericType;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import org.junit.After;
|
||||
import sonia.scm.util.IOUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -90,34 +91,9 @@ public class RepositoryITCase extends AbstractAdminITCaseBase
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Parameters
|
||||
public static Collection<String[]> createParameters()
|
||||
{
|
||||
Collection<String[]> params = new ArrayList<String[]>();
|
||||
|
||||
params.add(new String[] { "git" });
|
||||
|
||||
params.add(new String[] { "svn" });
|
||||
|
||||
if (IOUtil.search("hg") != null)
|
||||
{
|
||||
params.add(new String[] { "hg" });
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@After
|
||||
public void cleanup()
|
||||
{
|
||||
Client client = createClient();
|
||||
|
||||
authenticateAdmin(client);
|
||||
|
||||
Collection<Repository> repositories =
|
||||
createResource(client,
|
||||
"repositories").get(new GenericType<Collection<Repository>>() {}
|
||||
@@ -137,6 +113,29 @@ public class RepositoryITCase extends AbstractAdminITCaseBase
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Parameters
|
||||
public static Collection<String[]> createParameters()
|
||||
{
|
||||
Collection<String[]> params = Lists.newArrayList();
|
||||
|
||||
params.add(new String[] { "git" });
|
||||
params.add(new String[] { "svn" });
|
||||
|
||||
if (IOUtil.search("hg") != null)
|
||||
{
|
||||
params.add(new String[] { "hg" });
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
>>>>>>> merge rev
|
||||
*/
|
||||
@Test
|
||||
public void create()
|
||||
@@ -165,21 +164,18 @@ public class RepositoryITCase extends AbstractAdminITCaseBase
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void doubleCreate()
|
||||
{
|
||||
Repository repository = RepositoryTestData.create42Puzzle(repositoryType);
|
||||
|
||||
repository = createRepository(client, repository);
|
||||
|
||||
|
||||
WebResource wr = createResource(client, "repositories");
|
||||
ClientResponse response = wr.post(ClientResponse.class, repository);
|
||||
|
||||
|
||||
assertNotNull(response);
|
||||
|
||||
// TODO should be 409?
|
||||
assertEquals(500, response.getStatus());
|
||||
assertThat(response.getStatus(), not(lessThanOrEqualTo(400)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -142,7 +142,7 @@ public class RepositoryITCaseBase
|
||||
{
|
||||
RepositoryClient rc =
|
||||
RepositoryClientFactory.createClient(repository.getType(), directory,
|
||||
repository.createUrl(URL), username, password);
|
||||
repository.createUrl(BASE_URL), username, password);
|
||||
|
||||
rc.init();
|
||||
addTestFiles(rc);
|
||||
@@ -343,7 +343,7 @@ public class RepositoryITCaseBase
|
||||
throws RepositoryClientException
|
||||
{
|
||||
return RepositoryClientFactory.createClient(repository.getType(),
|
||||
directory, repository.createUrl(URL), user.getName(), password);
|
||||
directory, repository.createUrl(BASE_URL), user.getName(), password);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.net.ahc;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.net.TrustAllHostnameVerifier;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import sonia.scm.net.SSLContextProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultAdvancedHttpClientTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testApplyBaseSettings() throws IOException
|
||||
{
|
||||
new AdvancedHttpRequest(client, HttpMethod.GET,
|
||||
"https://www.scm-manager.org").request();
|
||||
verify(connection).setRequestMethod(HttpMethod.GET);
|
||||
verify(connection).setReadTimeout(DefaultAdvancedHttpClient.TIMEOUT_RAED);
|
||||
verify(connection).setConnectTimeout(
|
||||
DefaultAdvancedHttpClient.TIMEOUT_CONNECTION);
|
||||
verify(connection).addRequestProperty(HttpUtil.HEADER_CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
@Test(expected = ContentTransformerNotFoundException.class)
|
||||
public void testContentTransformerNotFound(){
|
||||
client.createTransformer(String.class, "text/plain");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContentTransformer(){
|
||||
ContentTransformer transformer = mock(ContentTransformer.class);
|
||||
when(transformer.isResponsible(String.class, "text/plain")).thenReturn(Boolean.TRUE);
|
||||
transformers.add(transformer);
|
||||
ContentTransformer t = client.createTransformer(String.class, "text/plain");
|
||||
assertSame(transformer, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testApplyContent() throws IOException
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
when(connection.getOutputStream()).thenReturn(baos);
|
||||
|
||||
AdvancedHttpRequestWithBody request =
|
||||
new AdvancedHttpRequestWithBody(client, HttpMethod.PUT,
|
||||
"https://www.scm-manager.org");
|
||||
|
||||
request.stringContent("test").request();
|
||||
verify(connection).setDoOutput(true);
|
||||
verify(connection).addRequestProperty(HttpUtil.HEADER_CONTENT_LENGTH, "4");
|
||||
assertEquals("test", baos.toString("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testApplyHeaders() throws IOException
|
||||
{
|
||||
AdvancedHttpRequest request = new AdvancedHttpRequest(client,
|
||||
HttpMethod.POST,
|
||||
"http://www.scm-manager.org");
|
||||
|
||||
request.header("Header-One", "One").header("Header-Two", "Two").request();
|
||||
verify(connection).setRequestMethod(HttpMethod.POST);
|
||||
verify(connection).addRequestProperty("Header-One", "One");
|
||||
verify(connection).addRequestProperty("Header-Two", "Two");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testApplyMultipleHeaders() throws IOException
|
||||
{
|
||||
AdvancedHttpRequest request = new AdvancedHttpRequest(client,
|
||||
HttpMethod.POST,
|
||||
"http://www.scm-manager.org");
|
||||
|
||||
request.header("Header-One", "One").header("Header-One", "Two").request();
|
||||
verify(connection).setRequestMethod(HttpMethod.POST);
|
||||
verify(connection).addRequestProperty("Header-One", "One");
|
||||
verify(connection).addRequestProperty("Header-One", "Two");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testBodyRequestWithoutContent() throws IOException
|
||||
{
|
||||
AdvancedHttpRequestWithBody request =
|
||||
new AdvancedHttpRequestWithBody(client, HttpMethod.PUT,
|
||||
"https://www.scm-manager.org");
|
||||
|
||||
request.request();
|
||||
verify(connection).addRequestProperty(HttpUtil.HEADER_CONTENT_LENGTH, "0");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testDisableCertificateValidation() throws IOException
|
||||
{
|
||||
AdvancedHttpRequest request = new AdvancedHttpRequest(client,
|
||||
HttpMethod.GET,
|
||||
"https://www.scm-manager.org");
|
||||
|
||||
request.disableCertificateValidation(true).request();
|
||||
verify(connection).setSSLSocketFactory(any(SSLSocketFactory.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testDisableHostnameValidation() throws IOException
|
||||
{
|
||||
AdvancedHttpRequest request = new AdvancedHttpRequest(client,
|
||||
HttpMethod.GET,
|
||||
"https://www.scm-manager.org");
|
||||
|
||||
request.disableHostnameValidation(true).request();
|
||||
verify(connection).setHostnameVerifier(any(TrustAllHostnameVerifier.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testIgnoreProxy() throws IOException
|
||||
{
|
||||
configuration.setProxyServer("proxy.scm-manager.org");
|
||||
configuration.setProxyPort(8090);
|
||||
configuration.setEnableProxy(true);
|
||||
new AdvancedHttpRequest(client, HttpMethod.GET,
|
||||
"https://www.scm-manager.org").ignoreProxySettings(true).request();
|
||||
assertFalse(client.proxyConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testProxyConnection() throws IOException
|
||||
{
|
||||
configuration.setProxyServer("proxy.scm-manager.org");
|
||||
configuration.setProxyPort(8090);
|
||||
configuration.setEnableProxy(true);
|
||||
new AdvancedHttpRequest(client, HttpMethod.GET,
|
||||
"https://www.scm-manager.org").request();
|
||||
assertTrue(client.proxyConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testProxyWithAuthentication() throws IOException
|
||||
{
|
||||
configuration.setProxyServer("proxy.scm-manager.org");
|
||||
configuration.setProxyPort(8090);
|
||||
configuration.setProxyUser("tricia");
|
||||
configuration.setProxyPassword("tricias secret");
|
||||
configuration.setEnableProxy(true);
|
||||
new AdvancedHttpRequest(client, HttpMethod.GET,
|
||||
"https://www.scm-manager.org").request();
|
||||
assertTrue(client.proxyConnection);
|
||||
verify(connection).addRequestProperty(
|
||||
DefaultAdvancedHttpClient.HEADER_PROXY_AUTHORIZATION,
|
||||
"Basic dHJpY2lhOnRyaWNpYXMgc2VjcmV0");
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
configuration = new ScmConfiguration();
|
||||
transformers = new HashSet<ContentTransformer>();
|
||||
client = new TestingAdvacedHttpClient(configuration, transformers);
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 15/05/01
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
public class TestingAdvacedHttpClient extends DefaultAdvancedHttpClient
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param configuration
|
||||
* @param transformers
|
||||
*/
|
||||
public TestingAdvacedHttpClient(ScmConfiguration configuration,
|
||||
Set<ContentTransformer> transformers)
|
||||
{
|
||||
super(configuration, transformers, new SSLContextProvider());
|
||||
}
|
||||
|
||||
//~--- methods ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
protected HttpURLConnection createConnection(URL url) throws IOException
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
* @param address
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
protected HttpURLConnection createProxyConnecton(URL url,
|
||||
SocketAddress address)
|
||||
throws IOException
|
||||
{
|
||||
proxyConnection = true;
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private boolean proxyConnection = false;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private TestingAdvacedHttpClient client;
|
||||
|
||||
/** Field description */
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private HttpsURLConnection connection;
|
||||
|
||||
/** Field description */
|
||||
private Set<ContentTransformer> transformers;
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.net.ahc;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import sonia.scm.net.SSLContextProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultAdvancedHttpResponseTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testContentAsByteSource() throws IOException
|
||||
{
|
||||
ByteArrayInputStream bais =
|
||||
new ByteArrayInputStream("test".getBytes(Charsets.UTF_8));
|
||||
|
||||
when(connection.getInputStream()).thenReturn(bais);
|
||||
|
||||
AdvancedHttpResponse response = new DefaultAdvancedHttpResponse(client,
|
||||
connection, 200, "OK");
|
||||
ByteSource content = response.contentAsByteSource();
|
||||
|
||||
assertEquals("test", content.asCharSource(Charsets.UTF_8).read());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testContentAsByteSourceWithFailedRequest() throws IOException
|
||||
{
|
||||
ByteArrayInputStream bais =
|
||||
new ByteArrayInputStream("test".getBytes(Charsets.UTF_8));
|
||||
|
||||
when(connection.getInputStream()).thenThrow(IOException.class);
|
||||
when(connection.getErrorStream()).thenReturn(bais);
|
||||
|
||||
AdvancedHttpResponse response = new DefaultAdvancedHttpResponse(client,
|
||||
connection, 404, "NOT FOUND");
|
||||
ByteSource content = response.contentAsByteSource();
|
||||
|
||||
assertEquals("test", content.asCharSource(Charsets.UTF_8).read());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetHeaders()
|
||||
{
|
||||
LinkedHashMap<String, List<String>> map = Maps.newLinkedHashMap();
|
||||
List<String> test = Lists.newArrayList("One", "Two");
|
||||
|
||||
map.put("Test", test);
|
||||
when(connection.getHeaderFields()).thenReturn(map);
|
||||
|
||||
AdvancedHttpResponse response = new DefaultAdvancedHttpResponse(client,
|
||||
connection, 200, "OK");
|
||||
Multimap<String, String> headers = response.getHeaders();
|
||||
|
||||
assertThat(headers.get("Test"), contains("One", "Two"));
|
||||
assertTrue(headers.get("Test-2").isEmpty());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final DefaultAdvancedHttpClient client =
|
||||
new DefaultAdvancedHttpClient(new ScmConfiguration(),
|
||||
new HashSet<ContentTransformer>(), new SSLContextProvider());
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private HttpURLConnection connection;
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.net.ahc;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.ByteSource;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class JsonContentTransformerTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testDoNotFailOnUnknownProperties() {
|
||||
ByteSource bs = ByteSource.wrap("{\"value\": \"test\", \"other\": \"test2\"}".getBytes(Charsets.UTF_8));
|
||||
TestObject obj = transformer.unmarshall(TestObject.class, bs);
|
||||
assertEquals("test", obj.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testIsResponsible()
|
||||
{
|
||||
assertTrue(transformer.isResponsible(String.class, "application/json"));
|
||||
assertTrue(transformer.isResponsible(String.class, "application/json;charset=UTF-8"));
|
||||
assertFalse(transformer.isResponsible(String.class, "text/plain"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testMarshallAndUnmarshall() throws IOException
|
||||
{
|
||||
ByteSource bs = transformer.marshall(new TestObject("test"));
|
||||
TestObject to = transformer.unmarshall(TestObject.class, bs);
|
||||
|
||||
assertEquals("test", to.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test(expected = ContentTransformerException.class)
|
||||
public void testUnmarshallIOException() throws IOException
|
||||
{
|
||||
ByteSource bs = mock(ByteSource.class);
|
||||
|
||||
when(bs.openBufferedStream()).thenThrow(IOException.class);
|
||||
transformer.unmarshall(String.class, bs);
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 15/10/21
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
@XmlRootElement(name = "test")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class TestObject
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
public TestObject() {}
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public TestObject(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 15/10/21
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
private static class TestObject2 {}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final JsonContentTransformer transformer = new JsonContentTransformer();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.net.ahc;
|
||||
|
||||
import com.google.common.io.ByteSource;
|
||||
import java.io.IOException;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class XmlContentTransformerTest {
|
||||
|
||||
private final XmlContentTransformer transformer = new XmlContentTransformer();
|
||||
|
||||
@Test
|
||||
public void testIsResponsible()
|
||||
{
|
||||
assertTrue(transformer.isResponsible(String.class, "application/xml"));
|
||||
assertTrue(transformer.isResponsible(String.class, "application/xml;charset=UTF-8"));
|
||||
assertFalse(transformer.isResponsible(String.class, "text/plain"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMarshallAndUnmarshall() throws IOException{
|
||||
ByteSource bs = transformer.marshall(new TestObject("test"));
|
||||
TestObject to = transformer.unmarshall(TestObject.class, bs);
|
||||
assertEquals("test", to.value);
|
||||
}
|
||||
|
||||
@Test(expected = ContentTransformerException.class)
|
||||
public void testUnmarshallIOException() throws IOException{
|
||||
ByteSource bs = mock(ByteSource.class);
|
||||
when(bs.openBufferedStream()).thenThrow(IOException.class);
|
||||
transformer.unmarshall(String.class, bs);
|
||||
}
|
||||
|
||||
private static class TestObject2 {}
|
||||
|
||||
@XmlRootElement(name = "test")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class TestObject {
|
||||
|
||||
private String value;
|
||||
|
||||
public TestObject()
|
||||
{
|
||||
}
|
||||
|
||||
public TestObject(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.resources;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractResourceManager}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractResourceManagerTest extends ResourceManagerTestBase
|
||||
{
|
||||
|
||||
private DummyResourceManager resourceManager;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Set<ResourceHandler> resourceHandlers = ImmutableSet.of(resourceHandler);
|
||||
resourceManager = new DummyResourceManager(pluginLoader, resourceHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link AbstractResourceManager#getScriptResources()} in the correct order.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*
|
||||
* @see <a href="https://goo.gl/ok03l4">Issue 809</a>
|
||||
*/
|
||||
@Test
|
||||
public void testGetScriptResources() throws IOException
|
||||
{
|
||||
appendScriptResources("a/b.js", "z/a.js", "a/a.js");
|
||||
List<String> scripts = resourceManager.getScriptResources();
|
||||
assertThat(scripts, contains("a/a.js", "a/b.js", "z/a.js"));
|
||||
}
|
||||
|
||||
private static class DummyResourceManager extends AbstractResourceManager
|
||||
{
|
||||
|
||||
public DummyResourceManager(PluginLoader pluginLoader, Set<ResourceHandler> resourceHandlers)
|
||||
{
|
||||
super(pluginLoader, resourceHandlers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void collectResources(Map<ResourceKey, Resource> resourceMap)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.resources;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultResourceManager}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultResourceManagerTest extends ResourceManagerTestBase {
|
||||
|
||||
private DefaultResourceManager resourceManager;
|
||||
|
||||
/**
|
||||
* Set up {@link DefaultResourceManager} for tests.
|
||||
*/
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Set<ResourceHandler> resourceHandlers = ImmutableSet.of(resourceHandler);
|
||||
resourceManager = new DefaultResourceManager(pluginLoader, resourceHandlers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link DefaultResourceManager#getResources(sonia.scm.resources.ResourceType)} method.
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
@Test
|
||||
public void testGetResources() throws IOException
|
||||
{
|
||||
appendScriptResources("a/b.js", "z/a.js", "a/a.js");
|
||||
List<Resource> resources = resourceManager.getResources(ResourceType.SCRIPT);
|
||||
assertEquals(1, resources.size());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.resources;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.servlet.ServletContext;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import sonia.scm.plugin.Plugin;
|
||||
import sonia.scm.plugin.PluginCondition;
|
||||
import sonia.scm.plugin.PluginInformation;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
import sonia.scm.plugin.PluginResources;
|
||||
import sonia.scm.plugin.PluginWrapper;
|
||||
import sonia.scm.plugin.WebResourceLoader;
|
||||
|
||||
/**
|
||||
* Base class for {@link ResourceManager} tests.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public abstract class ResourceManagerTestBase
|
||||
{
|
||||
|
||||
@Mock
|
||||
protected ServletContext servletContext;
|
||||
|
||||
@Mock
|
||||
protected PluginLoader pluginLoader;
|
||||
|
||||
@Mock
|
||||
protected ResourceHandler resourceHandler;
|
||||
|
||||
@Mock
|
||||
protected WebResourceLoader webResourceLoader;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder tempFolder = new TemporaryFolder();
|
||||
|
||||
/**
|
||||
* Append scripts resources to plugin loader.
|
||||
*
|
||||
* @param resources resource names
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void appendScriptResources(String... resources) throws IOException
|
||||
{
|
||||
Set<String> scripts = Sets.newHashSet(resources);
|
||||
Set<String> styles = Sets.newHashSet();
|
||||
Set<String> dependencies = Sets.newHashSet();
|
||||
|
||||
|
||||
Plugin plugin = new Plugin(
|
||||
2,
|
||||
new PluginInformation(),
|
||||
new PluginResources(scripts, styles),
|
||||
new PluginCondition(),
|
||||
false,
|
||||
dependencies
|
||||
);
|
||||
|
||||
Path pluginPath = tempFolder.newFolder().toPath();
|
||||
|
||||
PluginWrapper wrapper = new PluginWrapper(
|
||||
plugin,
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
webResourceLoader,
|
||||
pluginPath
|
||||
);
|
||||
|
||||
List<PluginWrapper> plugins = ImmutableList.of(wrapper);
|
||||
|
||||
when(pluginLoader.getInstalledPlugins()).thenReturn(plugins);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.schedule;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provider;
|
||||
import org.junit.Test;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.quartz.JobDataMap;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import sonia.scm.web.security.AdministrationContext;
|
||||
import sonia.scm.web.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link InjectionEnabledJob}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class InjectionEnabledJobTest {
|
||||
|
||||
@Mock
|
||||
private Injector injector;
|
||||
|
||||
@Mock
|
||||
private JobDataMap dataMap;
|
||||
|
||||
@Mock
|
||||
private JobDetail detail;
|
||||
|
||||
@Mock
|
||||
private JobExecutionContext jec;
|
||||
|
||||
@Mock
|
||||
private Provider<Runnable> runnable;
|
||||
|
||||
@Mock
|
||||
private AdministrationContext context;
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)} without context.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteWithoutContext() throws JobExecutionException
|
||||
{
|
||||
expected.expect(NullPointerException.class);
|
||||
expected.expectMessage("execution context");
|
||||
new InjectionEnabledJob().execute(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)} without job detail.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteWithoutJobDetail() throws JobExecutionException
|
||||
{
|
||||
expected.expect(NullPointerException.class);
|
||||
expected.expectMessage("detail");
|
||||
new InjectionEnabledJob().execute(jec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)} without data map.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteWithoutDataMap() throws JobExecutionException
|
||||
{
|
||||
when(jec.getJobDetail()).thenReturn(detail);
|
||||
expected.expect(NullPointerException.class);
|
||||
expected.expectMessage("data map");
|
||||
new InjectionEnabledJob().execute(jec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)} without injector.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteWithoutInjector() throws JobExecutionException
|
||||
{
|
||||
when(jec.getJobDetail()).thenReturn(detail);
|
||||
when(detail.getJobDataMap()).thenReturn(dataMap);
|
||||
expected.expect(NullPointerException.class);
|
||||
expected.expectMessage("injector");
|
||||
new InjectionEnabledJob().execute(jec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)} without runnable.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteWithoutRunnable() throws JobExecutionException
|
||||
{
|
||||
when(jec.getJobDetail()).thenReturn(detail);
|
||||
when(detail.getJobDataMap()).thenReturn(dataMap);
|
||||
when(dataMap.get(Injector.class.getName())).thenReturn(injector);
|
||||
expected.expect(JobExecutionException.class);
|
||||
expected.expectMessage("runnable");
|
||||
new InjectionEnabledJob().execute(jec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link InjectionEnabledJob#execute(org.quartz.JobExecutionContext)}.
|
||||
*
|
||||
* @throws JobExecutionException
|
||||
*/
|
||||
@Test
|
||||
public void testExecute() throws JobExecutionException
|
||||
{
|
||||
when(jec.getJobDetail()).thenReturn(detail);
|
||||
when(detail.getJobDataMap()).thenReturn(dataMap);
|
||||
when(dataMap.get(Injector.class.getName())).thenReturn(injector);
|
||||
when(dataMap.get(Runnable.class.getName())).thenReturn(runnable);
|
||||
when(injector.getInstance(AdministrationContext.class)).thenReturn(context);
|
||||
new InjectionEnabledJob().execute(jec);
|
||||
verify(context).runAsAdmin(Mockito.any(PrivilegedAction.class));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.schedule;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provider;
|
||||
import java.io.IOException;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.JobDetail;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.quartz.Trigger;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link QuartzScheduler}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuartzSchedulerTest {
|
||||
|
||||
@Mock
|
||||
private Injector injector;
|
||||
|
||||
@Mock
|
||||
private org.quartz.Scheduler quartzScheduler;
|
||||
|
||||
private QuartzScheduler scheduler;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
scheduler = new QuartzScheduler(injector, quartzScheduler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#schedule(java.lang.String, java.lang.Runnable)}.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testSchedule() throws SchedulerException
|
||||
{
|
||||
DummyRunnable dr = new DummyRunnable();
|
||||
Task task = scheduler.schedule("42 2 * * * ?", dr);
|
||||
assertNotNull(task);
|
||||
|
||||
ArgumentCaptor<JobDetail> detailCaptor = ArgumentCaptor.forClass(JobDetail.class);
|
||||
ArgumentCaptor<Trigger> triggerCaptor = ArgumentCaptor.forClass(Trigger.class);
|
||||
verify(quartzScheduler).scheduleJob(detailCaptor.capture(), triggerCaptor.capture());
|
||||
|
||||
Trigger trigger = triggerCaptor.getValue();
|
||||
assertThat(trigger, is(instanceOf(CronTrigger.class)));
|
||||
CronTrigger cron = (CronTrigger) trigger;
|
||||
assertEquals("42 2 * * * ?", cron.getCronExpression());
|
||||
|
||||
JobDetail detail = detailCaptor.getValue();
|
||||
assertEquals(InjectionEnabledJob.class, detail.getJobClass());
|
||||
Provider<Runnable> runnable = (Provider<Runnable>) detail.getJobDataMap().get(Runnable.class.getName());
|
||||
assertNotNull(runnable);
|
||||
assertSame(dr, runnable.get());
|
||||
assertEquals(injector, detail.getJobDataMap().get(Injector.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#schedule(java.lang.String, java.lang.Class)}.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testScheduleWithClass() throws SchedulerException
|
||||
{
|
||||
scheduler.schedule("42 * * * * ?", DummyRunnable.class);
|
||||
|
||||
verify(injector).getProvider(DummyRunnable.class);
|
||||
|
||||
ArgumentCaptor<JobDetail> detailCaptor = ArgumentCaptor.forClass(JobDetail.class);
|
||||
ArgumentCaptor<Trigger> triggerCaptor = ArgumentCaptor.forClass(Trigger.class);
|
||||
verify(quartzScheduler).scheduleJob(detailCaptor.capture(), triggerCaptor.capture());
|
||||
|
||||
Trigger trigger = triggerCaptor.getValue();
|
||||
assertThat(trigger, is(instanceOf(CronTrigger.class)));
|
||||
CronTrigger cron = (CronTrigger) trigger;
|
||||
assertEquals("42 * * * * ?", cron.getCronExpression());
|
||||
|
||||
JobDetail detail = detailCaptor.getValue();
|
||||
assertEquals(InjectionEnabledJob.class, detail.getJobClass());
|
||||
assertEquals(injector, detail.getJobDataMap().get(Injector.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#init(sonia.scm.SCMContextProvider)}.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testInit() throws SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenReturn(Boolean.FALSE);
|
||||
scheduler.init(null);
|
||||
verify(quartzScheduler).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#init(sonia.scm.SCMContextProvider)} when the underlying scheduler is already started.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testInitAlreadyRunning() throws SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenReturn(Boolean.TRUE);
|
||||
scheduler.init(null);
|
||||
verify(quartzScheduler, never()).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#init(sonia.scm.SCMContextProvider)} when the underlying scheduler throws an exception.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testInitException() throws SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenThrow(SchedulerException.class);
|
||||
scheduler.init(null);
|
||||
verify(quartzScheduler, never()).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#close()}.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testClose() throws IOException, SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenReturn(Boolean.TRUE);
|
||||
scheduler.close();
|
||||
verify(quartzScheduler).shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#close()} when the underlying scheduler is not running.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testCloseNotRunning() throws IOException, SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenReturn(Boolean.FALSE);
|
||||
scheduler.close();
|
||||
verify(quartzScheduler, never()).shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzScheduler#close()} when the underlying scheduler throws an exception.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testCloseException() throws IOException, SchedulerException
|
||||
{
|
||||
when(quartzScheduler.isStarted()).thenThrow(SchedulerException.class);
|
||||
scheduler.close();
|
||||
verify(quartzScheduler, never()).shutdown();
|
||||
}
|
||||
|
||||
|
||||
public static class DummyRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/***
|
||||
* Copyright (c) 2015, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* https://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.schedule;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.SchedulerException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link QuartzTask}.
|
||||
*
|
||||
* @author Sebastian Sdorra <sebastian.sdorra@triology.de>
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QuartzTaskTest {
|
||||
|
||||
@Mock
|
||||
private org.quartz.Scheduler scheduler;
|
||||
|
||||
private final JobKey jobKey = new JobKey("sample");
|
||||
|
||||
private QuartzTask task;
|
||||
|
||||
@Before
|
||||
public void setUp(){
|
||||
task = new QuartzTask(scheduler, jobKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzTask#cancel()}.
|
||||
*
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
@Test
|
||||
public void testCancel() throws SchedulerException
|
||||
{
|
||||
task.cancel();
|
||||
verify(scheduler).deleteJob(jobKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link QuartzTask#cancel()} when the scheduler throws an exception.
|
||||
* @throws org.quartz.SchedulerException
|
||||
*/
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void testCancelWithException() throws SchedulerException
|
||||
{
|
||||
when(scheduler.deleteJob(jobKey)).thenThrow(SchedulerException.class);
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.Permission;
|
||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||
import org.apache.shiro.authz.permission.PermissionResolver;
|
||||
import org.apache.shiro.authz.permission.WildcardPermission;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Rule;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import sonia.scm.HandlerEventType;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupEvent;
|
||||
import sonia.scm.group.GroupModificationEvent;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryDAO;
|
||||
import sonia.scm.repository.RepositoryEvent;
|
||||
import sonia.scm.repository.RepositoryModificationEvent;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserEvent;
|
||||
import sonia.scm.user.UserModificationEvent;
|
||||
import sonia.scm.user.UserTestData;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AuthorizationCollector}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultAuthorizationCollectorTest {
|
||||
|
||||
@Mock
|
||||
private Cache cache;
|
||||
|
||||
@Mock
|
||||
private CacheManager cacheManager;
|
||||
|
||||
@Mock
|
||||
private RepositoryDAO repositoryDAO;
|
||||
|
||||
@Mock
|
||||
private SecuritySystem securitySystem;
|
||||
|
||||
private DefaultAuthorizationCollector collector;
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
/**
|
||||
* Set up object to test.
|
||||
*/
|
||||
@Before
|
||||
public void setUp(){
|
||||
when(cacheManager.getCache(Mockito.any(String.class))).thenReturn(cache);
|
||||
|
||||
collector = new DefaultAuthorizationCollector(cacheManager, repositoryDAO, securitySystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.user.UserEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnUserEvent()
|
||||
{
|
||||
User user = UserTestData.createDent();
|
||||
collector.onEvent(new UserEvent(HandlerEventType.BEFORE_CREATE, user));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new UserEvent(HandlerEventType.CREATE, user));
|
||||
verify(cache).removeAll(Mockito.any(Predicate.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.user.UserEvent)} with modified user.
|
||||
*/
|
||||
@Test
|
||||
public void testOnUserModificationEvent()
|
||||
{
|
||||
User user = UserTestData.createDent();
|
||||
User userModified = UserTestData.createDent();
|
||||
userModified.setDisplayName("Super Dent");
|
||||
|
||||
collector.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
|
||||
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
|
||||
|
||||
collector.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
|
||||
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
|
||||
|
||||
userModified.setAdmin(true);
|
||||
|
||||
collector.onEvent(new UserModificationEvent(HandlerEventType.BEFORE_CREATE, userModified, user));
|
||||
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
|
||||
|
||||
collector.onEvent(new UserModificationEvent(HandlerEventType.CREATE, userModified, user));
|
||||
verify(cache).removeAll(Mockito.any(Predicate.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.group.GroupEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnGroupEvent()
|
||||
{
|
||||
Group group = new Group("xml", "base");
|
||||
collector.onEvent(new GroupEvent(HandlerEventType.BEFORE_CREATE, group));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new GroupEvent(HandlerEventType.CREATE, group));
|
||||
verify(cache).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.group.GroupEvent)} with modified groups.
|
||||
*/
|
||||
@Test
|
||||
public void testOnGroupModificationEvent()
|
||||
{
|
||||
Group group = new Group("xml", "base");
|
||||
Group modifiedGroup = new Group("xml", "base");
|
||||
collector.onEvent(new GroupModificationEvent(HandlerEventType.BEFORE_MODIFY, modifiedGroup, group));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
modifiedGroup.add("test");
|
||||
collector.onEvent(new GroupModificationEvent(HandlerEventType.MODIFY, modifiedGroup, group));
|
||||
verify(cache).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.repository.RepositoryEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnRepositoryEvent()
|
||||
{
|
||||
Repository repository = RepositoryTestData.createHeartOfGold();
|
||||
collector.onEvent(new RepositoryEvent(HandlerEventType.BEFORE_CREATE, repository));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new RepositoryEvent(HandlerEventType.CREATE, repository));
|
||||
verify(cache).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.repository.RepositoryEvent)} with modified repository.
|
||||
*/
|
||||
@Test
|
||||
public void testOnRepositoryModificationEvent()
|
||||
{
|
||||
Repository repositoryModified = RepositoryTestData.createHeartOfGold();
|
||||
repositoryModified.setName("test123");
|
||||
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
|
||||
|
||||
Repository repository = RepositoryTestData.createHeartOfGold();
|
||||
repository.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
|
||||
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.BEFORE_CREATE, repositoryModified, repository));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test")));
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
repositoryModified.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("test123")));
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
|
||||
verify(cache).clear();
|
||||
|
||||
repositoryModified.setPermissions(
|
||||
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.READ, true))
|
||||
);
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
|
||||
verify(cache, times(2)).clear();
|
||||
|
||||
repositoryModified.setPermissions(
|
||||
Lists.newArrayList(new sonia.scm.repository.Permission("test", PermissionType.WRITE))
|
||||
);
|
||||
collector.onEvent(new RepositoryModificationEvent(HandlerEventType.CREATE, repositoryModified, repository));
|
||||
verify(cache, times(3)).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#onEvent(sonia.scm.security.StoredAssignedPermissionEvent)}.
|
||||
*/
|
||||
@Test
|
||||
public void testOnStoredAssignedPermissionEvent()
|
||||
{
|
||||
StoredAssignedPermission groupPermission = new StoredAssignedPermission(
|
||||
"123", new AssignedPermission("_authenticated", true, "repository:read:*")
|
||||
);
|
||||
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, groupPermission));
|
||||
verify(cache, never()).clear();
|
||||
|
||||
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, groupPermission));
|
||||
verify(cache).clear();
|
||||
|
||||
|
||||
StoredAssignedPermission userPermission = new StoredAssignedPermission(
|
||||
"123", new AssignedPermission("trillian", false, "repository:read:*")
|
||||
);
|
||||
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.BEFORE_CREATE, userPermission));
|
||||
verify(cache, never()).removeAll(Mockito.any(Predicate.class));
|
||||
verify(cache).clear();
|
||||
|
||||
collector.onEvent(new StoredAssignedPermissionEvent(HandlerEventType.CREATE, userPermission));
|
||||
verify(cache).removeAll(Mockito.any(Predicate.class));
|
||||
verify(cache).clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} without user role.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware
|
||||
public void testCollectWithoutUserRole()
|
||||
{
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), nullValue());
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} from cache.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectFromCache()
|
||||
{
|
||||
AuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
when(cache.get(anyObject())).thenReturn(info);
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertSame(info, authInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with cache.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithCache(){
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
verify(cache).put(any(), any());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} without permissions.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithoutPermissions()
|
||||
{
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.contains(Role.USER));
|
||||
assertThat(authInfo.getStringPermissions(), hasSize(0));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} as admin.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectAsAdmin()
|
||||
{
|
||||
User trillian = UserTestData.createTrillian();
|
||||
trillian.setAdmin(true);
|
||||
authenticate(trillian, "main");
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER, Role.ADMIN));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), Matchers.contains("*"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with repository permissions.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithRepositoryPermissions()
|
||||
{
|
||||
String group = "heart-of-gold-crew";
|
||||
authenticate(UserTestData.createTrillian(), group);
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
heartOfGold.setId("one");
|
||||
heartOfGold.setPermissions(Lists.newArrayList(new sonia.scm.repository.Permission("trillian")));
|
||||
Repository puzzle42 = RepositoryTestData.create42Puzzle();
|
||||
puzzle42.setId("two");
|
||||
sonia.scm.repository.Permission permission = new sonia.scm.repository.Permission(group, PermissionType.WRITE, true);
|
||||
puzzle42.setPermissions(Lists.newArrayList(permission));
|
||||
when(repositoryDAO.getAll()).thenReturn(Lists.newArrayList(heartOfGold, puzzle42));
|
||||
|
||||
// execute and assert
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("repository:read:one", "repository:read,write:two"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with global permissions.
|
||||
*/
|
||||
@Test
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithGlobalPermissions(){
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
StoredAssignedPermission p1 = new StoredAssignedPermission("one", new AssignedPermission("one", "one:one"));
|
||||
StoredAssignedPermission p2 = new StoredAssignedPermission("two", new AssignedPermission("two", "two:two"));
|
||||
when(securitySystem.getPermissions(Mockito.any(Predicate.class))).thenReturn(Lists.newArrayList(p1, p2));
|
||||
|
||||
// execute and assert
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two"));
|
||||
}
|
||||
|
||||
private void authenticate(User user, String group, String... groups)
|
||||
{
|
||||
SimplePrincipalCollection spc = new SimplePrincipalCollection();
|
||||
spc.add(user.getName(), "unit");
|
||||
spc.add(user, "unit");
|
||||
spc.add(new GroupNames(group, groups), "unit");
|
||||
Subject subject = new Subject.Builder().authenticated(true).principals(spc).buildSubject();
|
||||
shiro.setSubject(subject);
|
||||
}
|
||||
|
||||
}
|
||||
108
scm-webapp/src/test/java/sonia/scm/security/XsrfCookiesTest.java
Normal file
108
scm-webapp/src/test/java/sonia/scm/security/XsrfCookiesTest.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Tests for the {@link XsrfCookies} util class.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class XsrfCookiesTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
/**
|
||||
* Prepare mocks for testing.
|
||||
*/
|
||||
@Before
|
||||
public void prepareMocks(){
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests create method.
|
||||
*/
|
||||
@Test
|
||||
public void testCreate()
|
||||
{
|
||||
XsrfCookies.create(request, response, "mytoken");
|
||||
|
||||
// capture cookie
|
||||
ArgumentCaptor<Cookie> captor = ArgumentCaptor.forClass(Cookie.class);
|
||||
verify(response).addCookie(captor.capture());
|
||||
|
||||
// check for cookie
|
||||
Cookie cookie = captor.getValue();
|
||||
assertEquals(XsrfProtectionFilter.KEY, cookie.getName());
|
||||
assertEquals("/scm", cookie.getPath());
|
||||
assertEquals("mytoken", cookie.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests remove method.
|
||||
*/
|
||||
@Test
|
||||
public void testRemove(){
|
||||
Cookie cookie = new Cookie(XsrfProtectionFilter.KEY, "mytoken");
|
||||
cookie.setMaxAge(15);
|
||||
when(request.getCookies()).thenReturn(new Cookie[]{cookie});
|
||||
XsrfCookies.remove(request, response);
|
||||
|
||||
// capture cookie
|
||||
ArgumentCaptor<Cookie> captor = ArgumentCaptor.forClass(Cookie.class);
|
||||
verify(response).addCookie(captor.capture());
|
||||
|
||||
// check the captured cookie
|
||||
Cookie c = captor.getValue();
|
||||
assertEquals("cookie max age should be set to 0", 0, c.getMaxAge());
|
||||
assertEquals("cookie path should be equals", cookie.getPath(), c.getPath());
|
||||
assertNull("cookie value shuld be null", c.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.util.HttpUtil;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link XsrfProtectionFilter}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class XsrfProtectionFilterTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
@Mock
|
||||
private HttpSession session;
|
||||
|
||||
@Mock
|
||||
private FilterChain chain;
|
||||
|
||||
private final ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
private final XsrfProtectionFilter filter = new XsrfProtectionFilter(configuration);
|
||||
|
||||
/**
|
||||
* Prepare mocks for testing.
|
||||
*/
|
||||
@Before
|
||||
public void setUp(){
|
||||
when(request.getSession(true)).thenReturn(session);
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
configuration.setEnabledXsrfProtection(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method for non web interface clients.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterFromNonWuiClient() throws IOException, ServletException
|
||||
{
|
||||
filter.doFilter(request, response, chain);
|
||||
verify(chain).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method with disabled xsrf protection.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterWithDisabledXsrfProtection() throws IOException, ServletException
|
||||
{
|
||||
// disable xsrf protection
|
||||
configuration.setEnabledXsrfProtection(false);
|
||||
|
||||
// set webui user-agent
|
||||
when(request.getHeader(HttpUtil.HEADER_SCM_CLIENT)).thenReturn(HttpUtil.SCM_CLIENT_WUI);
|
||||
|
||||
// call the filter
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// verify that no xsrf other any other cookie was set
|
||||
verify(response, never()).addCookie(Mockito.any(Cookie.class));
|
||||
|
||||
// ensure filter chain is called
|
||||
verify(chain).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method for first web interface request.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterIssuesTokenOnFirstWuiRequest() throws IOException, ServletException
|
||||
{
|
||||
when(request.getHeader(HttpUtil.HEADER_SCM_CLIENT)).thenReturn(HttpUtil.SCM_CLIENT_WUI);
|
||||
|
||||
// call the filter
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// capture cookie
|
||||
ArgumentCaptor<Cookie> captor = ArgumentCaptor.forClass(Cookie.class);
|
||||
verify(response).addCookie(captor.capture());
|
||||
|
||||
// check for cookie
|
||||
Cookie cookie = captor.getValue();
|
||||
assertEquals(XsrfProtectionFilter.KEY, cookie.getName());
|
||||
assertEquals("/scm", cookie.getPath());
|
||||
assertNotNull(cookie.getValue());
|
||||
|
||||
// ensure filter chain is called
|
||||
verify(chain).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method on protected session with an invalid xsrf token.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterWithInvalidToken() throws IOException, ServletException {
|
||||
when(request.getHeader(HttpUtil.HEADER_SCM_CLIENT)).thenReturn(HttpUtil.SCM_CLIENT_WUI);
|
||||
when(request.getHeader(XsrfProtectionFilter.KEY)).thenReturn("invalidtoken");
|
||||
when(session.getAttribute(XsrfProtectionFilter.KEY)).thenReturn("mytoken");
|
||||
|
||||
// call the filter
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// ensure response send forbidden and the chain was never called
|
||||
verify(response).sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method on protected session without xsrf token.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterOnProtectedSessionWithoutToken() throws IOException, ServletException {
|
||||
when(request.getHeader(HttpUtil.HEADER_SCM_CLIENT)).thenReturn(HttpUtil.SCM_CLIENT_WUI);
|
||||
when(session.getAttribute(XsrfProtectionFilter.KEY)).thenReturn("mytoken");
|
||||
|
||||
// call the filter
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// ensure response send forbidden and the chain was never called
|
||||
verify(response).sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
verify(chain, never()).doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter method on protected session with valid xsrf token.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoFilterOnProtectedSessionWithValidToken() throws IOException, ServletException {
|
||||
when(request.getHeader(HttpUtil.HEADER_SCM_CLIENT)).thenReturn(HttpUtil.SCM_CLIENT_WUI);
|
||||
when(request.getHeader(XsrfProtectionFilter.KEY)).thenReturn("mytoken");
|
||||
when(session.getAttribute(XsrfProtectionFilter.KEY)).thenReturn("mytoken");
|
||||
|
||||
// call the filter
|
||||
filter.doFilter(request, response, chain);
|
||||
|
||||
// ensure chain was called
|
||||
verify(chain).doFilter(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,25 +34,27 @@ package sonia.scm.selenium;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.selenium.page.Pages;
|
||||
import sonia.scm.selenium.page.MainPage;
|
||||
import sonia.scm.selenium.page.LoginPage;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Authentication related selenium integration tests.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class AuthenticationITCase extends SeleniumTestBase
|
||||
{
|
||||
public class AuthenticationITCase extends SeleniumITCaseBase {
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
* Authenticates an user and call logout function.
|
||||
*/
|
||||
@Test
|
||||
public void testAuthentication() throws Exception
|
||||
{
|
||||
login("scmadmin", "scmadmin");
|
||||
logout();
|
||||
public void testAuthentication() {
|
||||
MainPage main = Pages.get(driver, LoginPage.class).login("scmadmin", "scmadmin");
|
||||
assertEquals("scmadmin", main.getUserInfo());
|
||||
main.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,61 +34,55 @@ package sonia.scm.selenium;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.selenium.page.Pages;
|
||||
import sonia.scm.selenium.page.MainPage;
|
||||
import sonia.scm.selenium.page.LoginPage;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* Repository related selenium integration tests.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RepositoryCRUDITCase extends SeleniumTestBase
|
||||
{
|
||||
public class RepositoriesITCase extends SeleniumITCaseBase {
|
||||
|
||||
private MainPage main;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@After
|
||||
public void after()
|
||||
{
|
||||
logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void createRepository() throws InterruptedException
|
||||
{
|
||||
waitAndClick("#repositoryAddButton");
|
||||
waitForPresence("input[name=name]").sendKeys("scm");
|
||||
select("#x-form-el-repositoryType img").click();
|
||||
waitAndClick("div.x-combo-list-item:nth-of-type(2)");
|
||||
type("input[name=contact]", "scmadmin@scm-manager.org");
|
||||
type("textarea[name=description]", "SCM-Manager");
|
||||
waitAndClick("div.x-panel-btns button:nth-of-type(1)");
|
||||
|
||||
String name =
|
||||
waitForPresence(
|
||||
"div.x-grid3-row-selected div.x-grid3-col-name").getText();
|
||||
|
||||
assertEquals("scm", name);
|
||||
|
||||
waitAndClick("#repoRmButton button");
|
||||
waitAndClick("div.x-window button:nth-of-type(1)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
* Authenticates admin user, before each test.
|
||||
*/
|
||||
@Before
|
||||
public void login()
|
||||
{
|
||||
login("scmadmin", "scmadmin");
|
||||
public void login() {
|
||||
main = Pages.get(driver, LoginPage.class)
|
||||
.login("scmadmin", "scmadmin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates, select and removes a repository.
|
||||
*/
|
||||
@Test
|
||||
public void createRepository() {
|
||||
Repository repository = new Repository();
|
||||
repository.setName("scm");
|
||||
repository.setType("git");
|
||||
repository.setContact("scmadmin@scm-manager.org");
|
||||
repository.setDescription("SCM-Manager");
|
||||
|
||||
main.repositories()
|
||||
.add(repository)
|
||||
.select(repository.getName())
|
||||
.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the user out, after each test.
|
||||
*/
|
||||
@After
|
||||
public void logout() {
|
||||
main.logout();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.firefox.FirefoxDriver;
|
||||
|
||||
/**
|
||||
* Base class for selenium integration tests.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SeleniumITCaseBase {
|
||||
|
||||
/**
|
||||
* Selenium test driver.
|
||||
*/
|
||||
protected static WebDriver driver;
|
||||
|
||||
/**
|
||||
* Setup selenium test driver.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void setUpDriver() {
|
||||
// DesiredCapabilities capa = DesiredCapabilities.chrome();
|
||||
// capa.setBrowserName("firefox");
|
||||
// capa.setPlatform(Platform.ANY);
|
||||
// RemoteWebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capa);
|
||||
|
||||
driver = new FirefoxDriver();
|
||||
driver.get("http://localhost:8082/scm/index.html");
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the selenium test driver.
|
||||
*/
|
||||
@AfterClass
|
||||
public static void tearDownDriver() {
|
||||
driver.close();
|
||||
}
|
||||
}
|
||||
@@ -1,271 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.selenium;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.io.Files;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.OutputType;
|
||||
import org.openqa.selenium.TakesScreenshot;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.firefox.FirefoxDriver;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SeleniumTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for SeleniumTestBase
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(SeleniumTestBase.class);
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
driver.quit();
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
driver = new FirefoxDriver();
|
||||
baseUrl = "http://localhost:8082/scm/";
|
||||
open("index.html");
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
*/
|
||||
protected void login(String username, String password)
|
||||
{
|
||||
type("input[name=username]", username);
|
||||
type("input[name=password]", password);
|
||||
waitAndClick("#loginButton button");
|
||||
|
||||
String ue = waitForPresence("#scm-userinfo-tip").getText();
|
||||
|
||||
assertEquals(username, ue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
protected void logout()
|
||||
{
|
||||
waitAndClick("#navLogout a");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
protected void open(String url)
|
||||
{
|
||||
driver.get(baseUrl + url);
|
||||
pause(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param value
|
||||
* @param unit
|
||||
*/
|
||||
protected void pause(int value, TimeUnit unit)
|
||||
{
|
||||
driver.manage().timeouts().implicitlyWait(value, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
protected void screenshot(String target)
|
||||
{
|
||||
screenshot(new File(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param target
|
||||
*/
|
||||
protected void screenshot(File target)
|
||||
{
|
||||
try
|
||||
{
|
||||
File scrFile =
|
||||
((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
|
||||
|
||||
Files.copy(scrFile, target);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not create screenshot", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param cssSelector
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected WebElement select(String cssSelector)
|
||||
{
|
||||
WebElement element = driver.findElement(By.cssSelector(cssSelector));
|
||||
|
||||
assertNotNull(element);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param cssLocator
|
||||
* @param value
|
||||
*/
|
||||
protected void type(String cssLocator, String value)
|
||||
{
|
||||
select(cssLocator).clear();
|
||||
select(cssLocator).sendKeys(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
protected void waitAndClick(String query)
|
||||
{
|
||||
waitToBeClickable(query).click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param query
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected WebElement waitForPresence(String query)
|
||||
{
|
||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
||||
|
||||
return wait.until(
|
||||
ExpectedConditions.presenceOfElementLocated(By.cssSelector(query)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param query
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected WebElement waitToBeClickable(String query)
|
||||
{
|
||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
||||
|
||||
return wait.until(
|
||||
ExpectedConditions.elementToBeClickable(By.cssSelector(query)));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
protected WebDriver driver;
|
||||
|
||||
/** Field description */
|
||||
private String baseUrl;
|
||||
}
|
||||
168
scm-webapp/src/test/java/sonia/scm/selenium/page/BasePage.java
Normal file
168
scm-webapp/src/test/java/sonia/scm/selenium/page/BasePage.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.io.Files;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.OutputType;
|
||||
import org.openqa.selenium.TakesScreenshot;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
/**
|
||||
* Abstract selenium base page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*
|
||||
* @param <P> concrete page implementation
|
||||
*/
|
||||
public abstract class BasePage<P extends BasePage> {
|
||||
|
||||
/**
|
||||
* Selenium test driver.
|
||||
*/
|
||||
protected final WebDriver driver;
|
||||
|
||||
/**
|
||||
* Constructs a new base page.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
*/
|
||||
protected BasePage(WebDriver driver) {
|
||||
this.driver = driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link Thread#sleep(long)} for the given timeout.
|
||||
*
|
||||
* @param time timeout
|
||||
* @param unit time unit of timeout
|
||||
*/
|
||||
protected void sleep(long time, TimeUnit unit) {
|
||||
try {
|
||||
unit.sleep(time);
|
||||
} catch (InterruptedException ex) {
|
||||
throw Throwables.propagate(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the element until it is clickable.
|
||||
*
|
||||
* @param by element selector
|
||||
*
|
||||
* @return web element
|
||||
*/
|
||||
protected WebElement waitToBeClickable(By by){
|
||||
return waitToBeClickable(driver.findElement(by));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the element until it is clickable.
|
||||
*
|
||||
* @param element web element
|
||||
*
|
||||
* @return web element
|
||||
*/
|
||||
protected WebElement waitToBeClickable(WebElement element) {
|
||||
WebDriverWait wait = new WebDriverWait(driver, 5);
|
||||
|
||||
return wait.until(ExpectedConditions.elementToBeClickable(element));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until the element is present.
|
||||
*
|
||||
* @param by element locator
|
||||
*
|
||||
* @return web element
|
||||
*/
|
||||
protected WebElement waitFor(By by){
|
||||
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||
return wait.until(ExpectedConditions.presenceOfElementLocated(by));
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until the elements are present.
|
||||
*
|
||||
* @param by element selector
|
||||
*
|
||||
* @return list of web elements
|
||||
*/
|
||||
protected List<WebElement> waitForAll(By by){
|
||||
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||
return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a screenshot of the current browser content and stores it at the given path.
|
||||
*
|
||||
* @param target target file path
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
public P screenshot(String target) {
|
||||
return screenshot(new File(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a screenshot of the current browser content and stores it at the file.
|
||||
*
|
||||
* @param target target file
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
public P screenshot(File target) {
|
||||
try {
|
||||
File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
|
||||
|
||||
Files.copy(scrFile, target);
|
||||
} catch (IOException ex) {
|
||||
throw Throwables.propagate(ex);
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code this}.
|
||||
*
|
||||
* @return {@code this}
|
||||
*/
|
||||
protected abstract P self();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
/**
|
||||
* Page object for the scm-manager login page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class LoginPage extends BasePage<LoginPage> {
|
||||
|
||||
@FindBy(css = "input[name=username]")
|
||||
private WebElement usernameInput;
|
||||
|
||||
@FindBy(css = "input[name=password]")
|
||||
private WebElement passwordInput;
|
||||
|
||||
@FindBy(css = "#loginButton button")
|
||||
private WebElement loginButton;
|
||||
|
||||
/**
|
||||
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
*/
|
||||
LoginPage(WebDriver driver) {
|
||||
super(driver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoginPage self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates the user and returns the {@link MainPage}.
|
||||
*
|
||||
* @param username username
|
||||
* @param password password
|
||||
*
|
||||
* @return {@link MainPage} after successful authentication
|
||||
*/
|
||||
public MainPage login(String username, String password) {
|
||||
usernameInput.clear();
|
||||
usernameInput.sendKeys(username);
|
||||
|
||||
passwordInput.clear();
|
||||
passwordInput.sendKeys(password);
|
||||
|
||||
sleep(250, TimeUnit.MILLISECONDS);
|
||||
|
||||
waitToBeClickable(loginButton).click();
|
||||
|
||||
return Pages.get(driver, MainPage.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
/**
|
||||
* Page object for scm-manager's main page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class MainPage extends BasePage<MainPage> {
|
||||
|
||||
@FindBy(css = "#navLogout a")
|
||||
private WebElement logoutLink;
|
||||
|
||||
@FindBy(linkText = "Repositories")
|
||||
private WebElement repositoriesLink;
|
||||
|
||||
@FindBy(css = "#scm-userinfo-tip")
|
||||
private WebElement userInfoTip;
|
||||
|
||||
/**
|
||||
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
*/
|
||||
MainPage(WebDriver driver) {
|
||||
super(driver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MainPage self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the current authenticated user from the user info tip.
|
||||
*
|
||||
* @return name of the current authenticated user
|
||||
*/
|
||||
public String getUserInfo(){
|
||||
return userInfoTip.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the repositories page and returns the page object for this page.
|
||||
*
|
||||
* @return page object for repositories page
|
||||
*/
|
||||
public RepositoriesPage repositories(){
|
||||
repositoriesLink.click();
|
||||
return Pages.get(driver, RepositoriesPage.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the current user out.
|
||||
*
|
||||
* @return page object for the login
|
||||
*/
|
||||
public LoginPage logout(){
|
||||
waitToBeClickable(logoutLink).click();
|
||||
return Pages.get(driver, LoginPage.class);
|
||||
}
|
||||
}
|
||||
113
scm-webapp/src/test/java/sonia/scm/selenium/page/Pages.java
Normal file
113
scm-webapp/src/test/java/sonia/scm/selenium/page/Pages.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.SearchContext;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.PageFactory;
|
||||
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
/**
|
||||
* Helper class for selenium page objects.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public final class Pages {
|
||||
|
||||
private Pages() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the given page object.
|
||||
*
|
||||
* @param <T> page object type
|
||||
* @param driver selenium driver
|
||||
* @param clazz page object type
|
||||
* @param otherArguments other constructor arguments
|
||||
*
|
||||
* @return instance of page object
|
||||
*/
|
||||
public static <T extends BasePage> T get(WebDriver driver, Class<T> clazz, Object... otherArguments)
|
||||
{
|
||||
T page = null;
|
||||
try {
|
||||
List<Class<?>> argumentTypes = Lists.newArrayList();
|
||||
argumentTypes.add(WebDriver.class);
|
||||
for (Object argument : otherArguments) {
|
||||
argumentTypes.add(argument.getClass());
|
||||
}
|
||||
|
||||
List<Object> arguments = Lists.newArrayList();
|
||||
arguments.add(driver);
|
||||
arguments.addAll(Arrays.asList(otherArguments));
|
||||
|
||||
Constructor<T> constructor = clazz.getDeclaredConstructor(
|
||||
argumentTypes.toArray(new Class<?>[argumentTypes.size()])
|
||||
);
|
||||
page = constructor.newInstance(arguments.toArray(new Object[arguments.size()]));
|
||||
|
||||
PageFactory.initElements(new DefaultElementLocatorFactory(new WaitingSearchContext(driver)), page);
|
||||
} catch (Exception ex) {
|
||||
throw Throwables.propagate(ex);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
private static class WaitingSearchContext implements SearchContext {
|
||||
|
||||
private final WebDriver driver;
|
||||
private final WebDriverWait wait;
|
||||
|
||||
private WaitingSearchContext(WebDriver driver) {
|
||||
this.driver = driver;
|
||||
this.wait = new WebDriverWait(driver, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WebElement> findElements(By by) {
|
||||
return wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(by));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebElement findElement(By by) {
|
||||
return wait.until(ExpectedConditions.presenceOfElementLocated(by));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.List;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.NotFoundException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
/**
|
||||
* Page object for scm-manager's repository creation page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RepositoriesAddPage extends BasePage<RepositoriesAddPage> {
|
||||
|
||||
@FindBy(css = "input[name=name]")
|
||||
private WebElement nameInput;
|
||||
|
||||
@FindBy(css = "input[name=contact]")
|
||||
private WebElement contactInput;
|
||||
|
||||
@FindBy(css = "#x-form-el-repositoryType img")
|
||||
private WebElement typeInput;
|
||||
|
||||
@FindBy(css = "textarea[name=description]")
|
||||
private WebElement descriptionInput;
|
||||
|
||||
@FindBy(css = "div.x-panel-btns button:nth-of-type(1)")
|
||||
private WebElement okButton;
|
||||
|
||||
private final RepositoriesPage repositoriesPage;
|
||||
|
||||
/**
|
||||
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
* @param repositoriesPage repositories page object
|
||||
*/
|
||||
RepositoriesAddPage(WebDriver driver, RepositoriesPage repositoriesPage) {
|
||||
super(driver);
|
||||
this.repositoriesPage = repositoriesPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoriesAddPage self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Repository}.
|
||||
*
|
||||
* @param repository repository for creation
|
||||
*
|
||||
* @return repositories overview page
|
||||
*/
|
||||
public RepositoriesPage add(Repository repository) {
|
||||
nameInput.sendKeys(repository.getName());
|
||||
|
||||
selectType(repository.getType());
|
||||
|
||||
contactInput.sendKeys(repository.getContact());
|
||||
descriptionInput.sendKeys(repository.getDescription());
|
||||
|
||||
waitToBeClickable(okButton).click();
|
||||
|
||||
return repositoriesPage;
|
||||
}
|
||||
|
||||
private void selectType(String type) {
|
||||
typeInput.click();
|
||||
|
||||
String displayName = findDisplayName(type);
|
||||
|
||||
WebDriverWait wait = new WebDriverWait(driver, 1);
|
||||
List<WebElement> elements = waitForAll(By.className("x-combo-list-item"));
|
||||
WebElement typeElement = null;
|
||||
for (WebElement te : elements){
|
||||
if (te.getText().trim().equalsIgnoreCase(displayName)){
|
||||
typeElement = te;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeElement == null){
|
||||
throw new NotFoundException("could not find type element with type " + displayName);
|
||||
}
|
||||
|
||||
typeElement.click();
|
||||
}
|
||||
|
||||
private String findDisplayName(String type) {
|
||||
String displayName = null;
|
||||
if (driver instanceof JavascriptExecutor) {
|
||||
// TODO seams not to work
|
||||
String script = "Sonia.repository.getTypeByName('" + type + "').displayName;";
|
||||
displayName = (String) ((JavascriptExecutor)driver).executeScript(script);
|
||||
}
|
||||
return Objects.firstNonNull(displayName, type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.NotFoundException;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
/**
|
||||
* Page object for scm-manager's repositories overview page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RepositoriesPage extends BasePage<RepositoriesPage> {
|
||||
|
||||
@FindBy(id = "repositoryAddButton")
|
||||
private WebElement addButton;
|
||||
|
||||
/**
|
||||
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
*/
|
||||
RepositoriesPage(WebDriver driver) {
|
||||
super(driver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoriesPage self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Repository}.
|
||||
*
|
||||
* @param repository repository for creation
|
||||
*
|
||||
* @return {@link this}
|
||||
*/
|
||||
public RepositoriesPage add(Repository repository){
|
||||
addButton.click();
|
||||
RepositoriesAddPage addPage = Pages.get(driver, RepositoriesAddPage.class, this);
|
||||
return addPage.add(repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the repository with the given name and returns the detail page object for the selected repository.
|
||||
*
|
||||
* @param repositoryName name of the repository
|
||||
*
|
||||
* @return page object for selected repository
|
||||
*/
|
||||
public RepositoryPage select(String repositoryName){
|
||||
WebElement repositoryNameColumn = null;
|
||||
|
||||
List<WebElement> elements = waitForAll(By.className("x-grid3-col-name"));
|
||||
for (WebElement element : elements){
|
||||
if (element.getText().trim().toLowerCase(Locale.ENGLISH).equals(repositoryName)){
|
||||
repositoryNameColumn = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( repositoryNameColumn == null ) {
|
||||
throw new NotFoundException("could not find repository " + repositoryName);
|
||||
}
|
||||
|
||||
return Pages.get(driver, RepositoryPage.class, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
package sonia.scm.selenium.page;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.support.FindBy;
|
||||
|
||||
/**
|
||||
* Page object for scm-manager's repository detail page.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RepositoryPage extends BasePage<RepositoryPage> {
|
||||
|
||||
@FindBy(css = "#repoRmButton button")
|
||||
private WebElement removeButton;
|
||||
|
||||
private final RepositoriesPage repositoriesPage;
|
||||
|
||||
/**
|
||||
* Constructs a new page. This constructor should only be called from {@link Pages}.
|
||||
*
|
||||
* @param driver selenium test driver
|
||||
* @param repositoriesPage repositories page object
|
||||
*/
|
||||
RepositoryPage(WebDriver driver, RepositoriesPage repositoriesPage) {
|
||||
super(driver);
|
||||
this.repositoriesPage = repositoriesPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryPage self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the selected repository.
|
||||
*
|
||||
* @return repositories overview page object
|
||||
*/
|
||||
public RepositoriesPage remove(){
|
||||
removeButton.click();
|
||||
waitToBeClickable(By.cssSelector("div.x-window button:nth-of-type(1)")).click();
|
||||
return repositoriesPage;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,13 +55,25 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO add test with {@link UserAgentParser}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BasicWebTokenGeneratorTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Set up object under test.
|
||||
* Use {@code null} as {@link UserAgentParser}.
|
||||
*/
|
||||
@Before
|
||||
public void setUpObjectUnderTest() {
|
||||
generator = new BasicWebTokenGenerator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
@@ -132,10 +144,9 @@ public class BasicWebTokenGeneratorTest
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final BasicWebTokenGenerator generator = new BasicWebTokenGenerator();
|
||||
|
||||
|
||||
private BasicWebTokenGenerator generator;
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra <sebastian.sdorra@triology.de>
|
||||
*/
|
||||
public class BrowserUserAgentProviderTest
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final String CHROME =
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36";
|
||||
|
||||
/** Field description */
|
||||
private static final String FIREFOX =
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 5.2; en-GB; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18";
|
||||
|
||||
/** Field description */
|
||||
private static final String MSIE =
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; )";
|
||||
|
||||
/** Field description */
|
||||
private static final String OPERA =
|
||||
"Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.2.15 Version/10.00";
|
||||
|
||||
/** Field description */
|
||||
private static final String SAFARI =
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/6.1.3 Safari/537.75.14";
|
||||
|
||||
/** Field description */
|
||||
private static final String WGET = "Wget/1.5.3";
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testParseUserAgent()
|
||||
{
|
||||
assertEquals(BrowserUserAgentProvider.MSIE, parse(MSIE));
|
||||
assertEquals(BrowserUserAgentProvider.FIREFOX, parse(FIREFOX));
|
||||
assertEquals(BrowserUserAgentProvider.OPERA, parse(OPERA));
|
||||
assertEquals(BrowserUserAgentProvider.CHROME, parse(CHROME));
|
||||
assertEquals(BrowserUserAgentProvider.SAFARI, parse(SAFARI));
|
||||
assertNull(parse(WGET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private UserAgent parse(String v)
|
||||
{
|
||||
return provider.parseUserAgent(
|
||||
Strings.nullToEmpty(v).toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final BrowserUserAgentProvider provider =
|
||||
new BrowserUserAgentProvider();
|
||||
}
|
||||
Reference in New Issue
Block a user