mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 09:46:16 +01:00
merge
This commit is contained in:
@@ -17,6 +17,7 @@ import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -45,6 +46,23 @@ public class TemplatingPushStateDispatcherTest {
|
||||
|
||||
@Test
|
||||
public void testDispatch() throws IOException {
|
||||
TemplatingPushStateDispatcher.IndexHtmlModel model = dispatch();
|
||||
assertEquals("/scm", model.getContextPath());
|
||||
assertNull(model.getLiveReloadURL());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDispatchWithLiveReloadURL() throws IOException {
|
||||
System.setProperty("livereload.url", "/livereload.js");
|
||||
try {
|
||||
TemplatingPushStateDispatcher.IndexHtmlModel model = dispatch();
|
||||
assertEquals("/livereload.js", model.getLiveReloadURL());
|
||||
} finally {
|
||||
System.clearProperty("livereload.url");
|
||||
}
|
||||
}
|
||||
|
||||
private TemplatingPushStateDispatcher.IndexHtmlModel dispatch() throws IOException {
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
when(templateEngine.getTemplate(TemplatingPushStateDispatcher.TEMPLATE)).thenReturn(template);
|
||||
|
||||
@@ -59,8 +77,7 @@ public class TemplatingPushStateDispatcherTest {
|
||||
|
||||
verify(template).execute(any(Writer.class), captor.capture());
|
||||
|
||||
TemplatingPushStateDispatcher.IndexHtmlModel model = (TemplatingPushStateDispatcher.IndexHtmlModel) captor.getValue();
|
||||
assertEquals("/scm", model.getContextPath());
|
||||
return (TemplatingPushStateDispatcher.IndexHtmlModel) captor.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
@@ -19,7 +18,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
@@ -38,7 +36,6 @@ import java.util.List;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -50,7 +47,8 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
public static final String CHANGESET_PATH = "space/repo/changesets/";
|
||||
public static final String CHANGESET_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + CHANGESET_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
@@ -77,16 +75,14 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
public void prepareEnvironment() {
|
||||
changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||
changesetRootResource = new ChangesetRootResource(serviceFactory, changesetCollectionToDtoMapper, changesetToChangesetDtoMapper);
|
||||
super.changesetRootResource = Providers.of(changesetRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
|
||||
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
when(repositoryService.getLogCommand()).thenReturn(logCommandBuilder);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
@@ -169,7 +165,7 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
when(logCommandBuilder.setStartChangeset(anyString())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(CHANGESET_URL + "id")
|
||||
.get(CHANGESET_URL + id)
|
||||
.accept(VndMediaType.CHANGESET);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
@@ -8,9 +8,8 @@ import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.PathNotFoundException;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.api.CatCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -58,8 +57,8 @@ public class ContentResourceTest {
|
||||
when(catCommand.setRevision(REV)).thenReturn(catCommand);
|
||||
|
||||
// defaults for unknown things
|
||||
doThrow(new RepositoryNotFoundException("x")).when(repositoryServiceFactory).create(not(eq(existingNamespaceAndName)));
|
||||
doThrow(new PathNotFoundException("x")).when(catCommand).getStream(any());
|
||||
doThrow(new NotFoundException("Test", "r")).when(repositoryServiceFactory).create(not(eq(existingNamespaceAndName)));
|
||||
doThrow(new NotFoundException("Test", "X")).when(catCommand).getStream(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,7 +92,7 @@ public class ContentResourceTest {
|
||||
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "SomeGoCode.go");
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
assertEquals("GO", response.getHeaderString("Language"));
|
||||
assertEquals("GO", response.getHeaderString("X-Programming-Language"));
|
||||
assertEquals("text/x-go", response.getHeaderString("Content-Type"));
|
||||
}
|
||||
|
||||
@@ -104,7 +103,7 @@ public class ContentResourceTest {
|
||||
Response response = contentResource.get(NAMESPACE, REPO_NAME, REV, "Dockerfile");
|
||||
assertEquals(200, response.getStatus());
|
||||
|
||||
assertEquals("DOCKERFILE", response.getHeaderString("Language"));
|
||||
assertEquals("DOCKERFILE", response.getHeaderString("X-Programming-Language"));
|
||||
assertEquals("text/plain", response.getHeaderString("Content-Type"));
|
||||
}
|
||||
|
||||
@@ -175,7 +174,7 @@ public class ContentResourceTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,20 +17,23 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.api.v2.NotFoundExceptionMapper;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.DiffCommandBuilder;
|
||||
import sonia.scm.repository.api.DiffFormat;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -62,14 +65,15 @@ public class DiffResourceTest extends RepositoryTestBase {
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
public void prepareEnvironment() {
|
||||
diffRootResource = new DiffRootResource(serviceFactory);
|
||||
super.diffRootResource = Providers.of(diffRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl();
|
||||
dispatcher.getProviderFactory().register(new NotFoundExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(CRLFInjectionExceptionMapper.class);
|
||||
when(service.getDiffCommand()).thenReturn(diffCommandBuilder);
|
||||
@@ -86,19 +90,17 @@ public class DiffResourceTest extends RepositoryTestBase {
|
||||
@Test
|
||||
public void shouldGetDiffs() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenReturn(diffCommandBuilder);
|
||||
|
||||
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retrieveContent(any())).thenReturn(diffCommandBuilder);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
log.info("Response :{}", response.getContentAsString());
|
||||
|
||||
assertThat(response.getStatus())
|
||||
.isEqualTo(200);
|
||||
assertThat(response.getContentAsString())
|
||||
.isNotNull();
|
||||
String expectedHeader = "Content-Disposition";
|
||||
String expectedValue = "attachment; filename=\"repo-revision.diff\"; filename*=utf-8''repo-revision.diff";
|
||||
assertThat(response.getOutputHeaders().containsKey(expectedHeader)).isTrue();
|
||||
@@ -107,8 +109,8 @@ public class DiffResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(RepositoryNotFoundException.class);
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x"));
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
@@ -120,20 +122,24 @@ public class DiffResourceTest extends RepositoryTestBase {
|
||||
@Test
|
||||
public void shouldGet404OnMissingRevision() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenThrow(RevisionNotFoundException.class);
|
||||
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x"));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400OnCrlfInjection() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retriveContent(any())).thenThrow(RevisionNotFoundException.class);
|
||||
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Text", "x"));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "ny%0D%0ASet-cookie:%20Tamper=3079675143472450634")
|
||||
@@ -143,6 +149,47 @@ public class DiffResourceTest extends RepositoryTestBase {
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400OnUnknownFormat() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retrieveContent(any())).thenThrow(new NotFoundException("Test", "test"));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision?format=Unknown")
|
||||
.accept(VndMediaType.DIFF);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptDiffFormats() throws Exception {
|
||||
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
|
||||
when(diffCommandBuilder.retrieveContent(any())).thenReturn(diffCommandBuilder);
|
||||
|
||||
Arrays.stream(DiffFormat.values()).map(DiffFormat::name).forEach(
|
||||
this::assertRequestOk
|
||||
);
|
||||
}
|
||||
|
||||
private void assertRequestOk(String format) {
|
||||
MockHttpRequest request = null;
|
||||
try {
|
||||
request = MockHttpRequest
|
||||
.get(DIFF_URL + "revision?format=" + format)
|
||||
.accept(VndMediaType.DIFF);
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
fail("got exception: " + e);
|
||||
}
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertThat(response.getStatus())
|
||||
.withFailMessage("diff format from DiffFormat enum must be accepted: " + format)
|
||||
.isEqualTo(200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,20 +5,22 @@ import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import sonia.scm.api.rest.AlreadyExistsExceptionMapper;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.api.rest.ConcurrentModificationExceptionMapper;
|
||||
import sonia.scm.api.rest.IllegalArgumentExceptionMapper;
|
||||
import sonia.scm.api.v2.NotFoundExceptionMapper;
|
||||
import sonia.scm.api.v2.NotSupportedFeatureExceptionMapper;
|
||||
|
||||
public class DispatcherMock {
|
||||
public static Dispatcher createDispatcher(Object resource) {
|
||||
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
dispatcher.getRegistry().addSingletonResource(resource);
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AlreadyExistsExceptionMapper.class);
|
||||
ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl();
|
||||
dispatcher.getProviderFactory().register(new NotFoundExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new AlreadyExistsExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new ConcurrentModificationExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(ConcurrentModificationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(ChangePasswordNotAllowedExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InvalidPasswordExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(IllegalArgumentExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().register(new InternalRepositoryExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new ChangePasswordNotAllowedExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new InvalidPasswordExceptionMapper(mapper));
|
||||
dispatcher.getProviderFactory().register(new NotSupportedFeatureExceptionMapper(mapper));
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
@@ -18,15 +17,14 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Person;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.LogCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -52,7 +50,6 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
|
||||
public static final String FILE_HISTORY_PATH = "space/repo/history/";
|
||||
public static final String FILE_HISTORY_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + FILE_HISTORY_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
@@ -73,23 +70,21 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
|
||||
private FileHistoryRootResource fileHistoryRootResource;
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
public void prepareEnvironment() {
|
||||
fileHistoryCollectionToDtoMapper = new FileHistoryCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
|
||||
fileHistoryRootResource = new FileHistoryRootResource(serviceFactory, fileHistoryCollectionToDtoMapper);
|
||||
super.fileHistoryRootResource = Providers.of(fileHistoryRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl();
|
||||
when(service.getLogCommand()).thenReturn(logCommandBuilder);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
@@ -133,8 +128,8 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(RepositoryNotFoundException.class);
|
||||
public void shouldGet404OnMissingRepository() throws URISyntaxException {
|
||||
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x"));
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + "revision/a.txt")
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
@@ -152,7 +147,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(RevisionNotFoundException.class);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(new NotFoundException("Text", "x"));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
@@ -171,7 +166,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(eq(id))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPath(eq(path))).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(InternalRepositoryException.class);
|
||||
when(logCommandBuilder.getChangesets()).thenThrow(new InternalRepositoryException(ContextEntry.ContextBuilder.noContext(), "", new RuntimeException()));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(FILE_HISTORY_URL + id + "/" + path)
|
||||
@@ -182,7 +177,7 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet500OnNullChangesets() throws Exception {
|
||||
public void shouldGet404OnNullChangesets() throws Exception {
|
||||
String id = "revision_123";
|
||||
String path = "root_dir/sub_dir/file-to-inspect.txt";
|
||||
|
||||
@@ -197,6 +192,6 @@ public class FileHistoryResourceTest extends RepositoryTestBase {
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(500, response.getStatus());
|
||||
assertEquals(404, response.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class GroupRootResourceTest {
|
||||
private ArgumentCaptor<Group> groupCaptor = ArgumentCaptor.forClass(Group.class);
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
when(groupManager.create(groupCaptor.capture())).thenAnswer(invocation -> invocation.getArguments()[0]);
|
||||
doNothing().when(groupManager).modify(groupCaptor.capture());
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.user.InvalidPasswordException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
@@ -168,7 +169,8 @@ public class MeResourceTest {
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(InvalidPasswordException.class).when(userManager).changePasswordForLoggedInUser(any(), any());
|
||||
doThrow(new InvalidPasswordException(ContextEntry.ContextBuilder.entity("passwortChange", "-")))
|
||||
.when(userManager).changePasswordForLoggedInUser(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
@@ -18,7 +17,6 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.repository.Modifications;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
@@ -37,6 +35,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.noContext;
|
||||
|
||||
@Slf4j
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@@ -45,7 +44,8 @@ public class ModificationsResourceTest extends RepositoryTestBase {
|
||||
|
||||
public static final String MODIFICATIONS_PATH = "space/repo/modifications/";
|
||||
public static final String MODIFICATIONS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + MODIFICATIONS_PATH;
|
||||
private final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
@@ -70,16 +70,13 @@ public class ModificationsResourceTest extends RepositoryTestBase {
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
public void prepareEnvironment() {
|
||||
modificationsRootResource = new ModificationsRootResource(serviceFactory, modificationsToDtoMapper);
|
||||
super.modificationsRootResource = Providers.of(modificationsRootResource);
|
||||
dispatcher.getRegistry().addSingletonResource(getRepositoryRootResource());
|
||||
dispatcher = DispatcherMock.createDispatcher(getRepositoryRootResource());
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService);
|
||||
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo"));
|
||||
dispatcher.getProviderFactory().registerProvider(NotFoundExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(AuthorizationExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
when(repositoryService.getModificationsCommand()).thenReturn(modificationsCommandBuilder);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
@@ -107,7 +104,7 @@ public class ModificationsResourceTest extends RepositoryTestBase {
|
||||
@Test
|
||||
public void shouldGet500OnModificationsCommandError() throws Exception {
|
||||
when(modificationsCommandBuilder.revision(any())).thenReturn(modificationsCommandBuilder);
|
||||
when(modificationsCommandBuilder.getModifications()).thenThrow(InternalRepositoryException.class);
|
||||
when(modificationsCommandBuilder.getModifications()).thenThrow(new InternalRepositoryException(noContext(), "", new RuntimeException()));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(MODIFICATIONS_URL + "revision")
|
||||
|
||||
@@ -164,10 +164,7 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
@TestFactory
|
||||
@DisplayName("test endpoints on missing permissions and user is Admin")
|
||||
Stream<DynamicTest> missedPermissionTestFactory() {
|
||||
Repository mockRepository = mock(Repository.class);
|
||||
when(mockRepository.getId()).thenReturn(REPOSITORY_NAME);
|
||||
when(mockRepository.getNamespace()).thenReturn(REPOSITORY_NAMESPACE);
|
||||
when(mockRepository.getName()).thenReturn(REPOSITORY_NAME);
|
||||
Repository mockRepository = new Repository(REPOSITORY_NAME, "git", REPOSITORY_NAMESPACE, REPOSITORY_NAME);
|
||||
when(repositoryManager.get(any(NamespaceAndName.class))).thenReturn(mockRepository);
|
||||
return createDynamicTestsToAssertResponses(
|
||||
requestGETPermission.expectedResponseStatus(404),
|
||||
@@ -180,10 +177,6 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
@TestFactory
|
||||
@DisplayName("test endpoints on missing permissions and user is not Admin")
|
||||
Stream<DynamicTest> missedPermissionUserForbiddenTestFactory() {
|
||||
Repository mockRepository = mock(Repository.class);
|
||||
when(mockRepository.getId()).thenReturn(REPOSITORY_NAME);
|
||||
when(mockRepository.getNamespace()).thenReturn(REPOSITORY_NAMESPACE);
|
||||
when(mockRepository.getName()).thenReturn(REPOSITORY_NAME);
|
||||
doThrow(AuthorizationException.class).when(repositoryManager).get(any(NamespaceAndName.class));
|
||||
return createDynamicTestsToAssertResponses(
|
||||
requestGETPermission.expectedResponseStatus(403),
|
||||
@@ -409,17 +402,17 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
private Repository createUserWithRepository(String userPermission) {
|
||||
Repository mockRepository = mock(Repository.class);
|
||||
when(mockRepository.getId()).thenReturn(REPOSITORY_NAME);
|
||||
when(mockRepository.getNamespace()).thenReturn(REPOSITORY_NAMESPACE);
|
||||
when(mockRepository.getName()).thenReturn(REPOSITORY_NAME);
|
||||
Repository mockRepository = new Repository();
|
||||
mockRepository.setId(REPOSITORY_NAME);
|
||||
mockRepository.setNamespace(REPOSITORY_NAMESPACE);
|
||||
mockRepository.setName(REPOSITORY_NAME);
|
||||
when(repositoryManager.get(any(NamespaceAndName.class))).thenReturn(mockRepository);
|
||||
when(subject.isPermitted(userPermission != null ? eq(userPermission) : any(String.class))).thenReturn(true);
|
||||
return mockRepository;
|
||||
}
|
||||
|
||||
private void createUserWithRepositoryAndPermissions(ArrayList<Permission> permissions, String userPermission) {
|
||||
when(createUserWithRepository(userPermission).getPermissions()).thenReturn(permissions);
|
||||
createUserWithRepository(userPermission).setPermissions(permissions);
|
||||
}
|
||||
|
||||
private Stream<DynamicTest> createDynamicTestsToAssertResponses(ExpectedRequest... expectedRequests) {
|
||||
@@ -427,10 +420,9 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
.map(entry -> dynamicTest("the endpoint " + entry.description + " should return the status code " + entry.expectedResponseStatus, () -> assertExpectedRequest(entry)));
|
||||
}
|
||||
|
||||
private MockHttpResponse assertExpectedRequest(ExpectedRequest entry) throws URISyntaxException {
|
||||
private void assertExpectedRequest(ExpectedRequest entry) throws URISyntaxException {
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
HttpRequest request = null;
|
||||
request = MockHttpRequest
|
||||
HttpRequest request = MockHttpRequest
|
||||
.create(entry.method, "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + entry.path)
|
||||
.content(entry.content)
|
||||
.contentType(VndMediaType.PERMISSION);
|
||||
@@ -442,7 +434,6 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
if (entry.responseValidator != null) {
|
||||
entry.responseValidator.accept(response);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@ToString
|
||||
@@ -476,12 +467,12 @@ public class PermissionRootResourceTest extends RepositoryTestBase {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedRequest expectedResponseStatus(int expectedResponseStatus) {
|
||||
ExpectedRequest expectedResponseStatus(int expectedResponseStatus) {
|
||||
this.expectedResponseStatus = expectedResponseStatus;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedRequest responseValidator(Consumer<MockHttpResponse> responseValidator) {
|
||||
ExpectedRequest responseValidator(Consumer<MockHttpResponse> responseValidator) {
|
||||
this.responseValidator = responseValidator;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.io.Resources;
|
||||
import com.google.inject.util.Providers;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
@@ -22,6 +25,7 @@ import sonia.scm.repository.RepositoryIsNotArchivedException;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -37,6 +41,7 @@ import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -59,6 +64,8 @@ import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
)
|
||||
public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
private static final String REALM = "AdminRealm";
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
@Rule
|
||||
@@ -96,6 +103,13 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(scmPathInfoStore.get()).thenReturn(uriInfo);
|
||||
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y"));
|
||||
SimplePrincipalCollection trillian = new SimplePrincipalCollection("trillian", REALM);
|
||||
trillian.add(new User("trillian"), REALM);
|
||||
shiro.setSubject(
|
||||
new Subject.Builder()
|
||||
.principals(trillian)
|
||||
.authenticated(true)
|
||||
.buildSubject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -257,6 +271,34 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
verify(repositoryManager).create(any(Repository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetCurrentUserAsOwner() throws Exception {
|
||||
ArgumentCaptor<Repository> createCaptor = ArgumentCaptor.forClass(Repository.class);
|
||||
when(repositoryManager.create(createCaptor.capture())).thenAnswer(invocation -> {
|
||||
Repository repository = (Repository) invocation.getArguments()[0];
|
||||
repository.setNamespace("otherspace");
|
||||
return repository;
|
||||
});
|
||||
|
||||
URL url = Resources.getResource("sonia/scm/api/v2/repository-test-update.json");
|
||||
byte[] repositoryJson = Resources.toByteArray(url);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2)
|
||||
.contentType(VndMediaType.REPOSITORY)
|
||||
.content(repositoryJson);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
Assertions.assertThat(createCaptor.getValue().getPermissions())
|
||||
.hasSize(1)
|
||||
.allSatisfy(p -> {
|
||||
assertThat(p.getName()).isEqualTo("trillian");
|
||||
assertThat(p.getType()).isEqualTo(PermissionType.OWNER);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotOverwriteExistingPermissionsOnUpdate() throws Exception {
|
||||
Repository existingRepository = mockRepository("space", "repo");
|
||||
|
||||
@@ -14,7 +14,6 @@ import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.FileObject;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.api.BrowseCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -60,7 +59,7 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSources() throws URISyntaxException, IOException, NotFoundException {
|
||||
public void shouldReturnSources() throws URISyntaxException, IOException {
|
||||
BrowserResult result = createBrowserResult();
|
||||
when(browseCommandBuilder.getBrowserResult()).thenReturn(result);
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/sources");
|
||||
@@ -74,8 +73,8 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturn404IfRepoNotFound() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(new NamespaceAndName("idont", "exist"))).thenThrow(RepositoryNotFoundException.class);
|
||||
public void shouldReturn404IfRepoNotFound() throws URISyntaxException {
|
||||
when(serviceFactory.create(new NamespaceAndName("idont", "exist"))).thenThrow(new NotFoundException("Test", "a"));
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "idont/exist/sources");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
@@ -84,7 +83,7 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetResultForSingleFile() throws URISyntaxException, IOException, NotFoundException {
|
||||
public void shouldGetResultForSingleFile() throws URISyntaxException, IOException {
|
||||
FileObject fileObject = new FileObject();
|
||||
fileObject.setName("File Object!");
|
||||
fileObject.setPath("/");
|
||||
@@ -100,8 +99,8 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404ForSingleFileIfRepoNotFound() throws URISyntaxException, RepositoryNotFoundException {
|
||||
when(serviceFactory.create(new NamespaceAndName("idont", "exist"))).thenThrow(RepositoryNotFoundException.class);
|
||||
public void shouldGet404ForSingleFileIfRepoNotFound() throws URISyntaxException {
|
||||
when(serviceFactory.create(new NamespaceAndName("idont", "exist"))).thenThrow(new NotFoundException("Test", "a"));
|
||||
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "idont/exist/sources/revision/fileabc");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.api.v2.NotFoundExceptionMapper;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.Tag;
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.ContextEntry;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.user.ChangePasswordNotAllowedException;
|
||||
@@ -102,7 +103,7 @@ public class UserRootResourceTest {
|
||||
@Test
|
||||
public void shouldGet400OnCreatingNewUserWithNotAllowedCharacters() throws URISyntaxException {
|
||||
// the @ character at the begin of the name is not allowed
|
||||
String userJson = "{ \"name\": \"@user\", \"type\": \"db\" }";
|
||||
String userJson = "{ \"name\": \"@user\",\"active\": true,\"admin\": false,\"displayName\": \"someone\",\"mail\": \"x@example.com\",\"type\": \"db\" }";
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.post("/" + UserRootResource.USERS_PATH_V2)
|
||||
.contentType(VndMediaType.USER)
|
||||
@@ -114,7 +115,7 @@ public class UserRootResourceTest {
|
||||
assertEquals(400, response.getStatus());
|
||||
|
||||
// the whitespace at the begin opf the name is not allowed
|
||||
userJson = "{ \"name\": \" user\", \"type\": \"db\" }";
|
||||
userJson = "{ \"name\": \" user\",\"active\": true,\"admin\": false,\"displayName\": \"someone\",\"mail\": \"x@example.com\",\"type\": \"db\" }";
|
||||
request = MockHttpRequest
|
||||
.post("/" + UserRootResource.USERS_PATH_V2)
|
||||
.contentType(VndMediaType.USER)
|
||||
@@ -167,7 +168,7 @@ public class UserRootResourceTest {
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(ChangePasswordNotAllowedException.class).when(userManager).overwritePassword(any(), any());
|
||||
doThrow(new ChangePasswordNotAllowedException(ContextEntry.ContextBuilder.entity("passwordChange", "-"), "xml")).when(userManager).overwritePassword(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
@@ -185,7 +186,7 @@ public class UserRootResourceTest {
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(NotFoundException.class).when(userManager).overwritePassword(any(), any());
|
||||
doThrow(new NotFoundException("Test", "x")).when(userManager).overwritePassword(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
|
||||
133
scm-webapp/src/test/java/sonia/scm/boot/RestartServletTest.java
Normal file
133
scm-webapp/src/test/java/sonia/scm/boot/RestartServletTest.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package sonia.scm.boot;
|
||||
|
||||
import com.github.legman.Subscribe;
|
||||
import com.google.common.base.Charsets;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.Stage;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.event.ScmTestEventBus;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RestartServletTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
|
||||
private RestartServlet restartServlet;
|
||||
|
||||
private EventListener listener;
|
||||
|
||||
private void setUpObjectUnderTest(Stage stage) {
|
||||
listener = new EventListener();
|
||||
ScmEventBus eventBus = ScmTestEventBus.getInstance();
|
||||
eventBus.register(listener);
|
||||
|
||||
restartServlet = new RestartServlet(eventBus, stage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestart() throws IOException {
|
||||
setUpObjectUnderTest(Stage.DEVELOPMENT);
|
||||
setRequestInputReason("something changed");
|
||||
|
||||
restartServlet.doPost(request, response);
|
||||
|
||||
verify(response).setStatus(HttpServletResponse.SC_ACCEPTED);
|
||||
|
||||
RestartEvent restartEvent = listener.restartEvent;
|
||||
assertThat(restartEvent).isNotNull();
|
||||
assertThat(restartEvent.getCause()).isEqualTo(RestartServlet.class);
|
||||
assertThat(restartEvent.getReason()).isEqualTo("something changed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestartCalledTwice() throws IOException {
|
||||
setUpObjectUnderTest(Stage.DEVELOPMENT);
|
||||
|
||||
setRequestInputReason("initial change");
|
||||
restartServlet.doPost(request, response);
|
||||
verify(response).setStatus(HttpServletResponse.SC_ACCEPTED);
|
||||
|
||||
setRequestInputReason("changed again");
|
||||
restartServlet.doPost(request, response);
|
||||
verify(response).setStatus(HttpServletResponse.SC_CONFLICT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestartWithInvalidContent() throws IOException {
|
||||
setUpObjectUnderTest(Stage.DEVELOPMENT);
|
||||
|
||||
setRequestInputContent("invalid json");
|
||||
|
||||
restartServlet.doPost(request, response);
|
||||
|
||||
verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestartInProductionStage() throws IOException {
|
||||
setUpObjectUnderTest(Stage.PRODUCTION);
|
||||
|
||||
setRequestInputReason("initial change");
|
||||
|
||||
restartServlet.doPost(request, response);
|
||||
|
||||
verify(response).setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
|
||||
}
|
||||
|
||||
private void setRequestInputReason(String message) throws IOException {
|
||||
String content = createReason(message);
|
||||
setRequestInputContent(content);
|
||||
}
|
||||
|
||||
private void setRequestInputContent(String content) throws IOException {
|
||||
InputStream input = createReasonAsInputStream(content);
|
||||
when(request.getInputStream()).thenReturn(createServletInputStream(input));
|
||||
}
|
||||
|
||||
private ServletInputStream createServletInputStream(final InputStream inputStream) {
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return inputStream.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private InputStream createReasonAsInputStream(String content) {
|
||||
return new ByteArrayInputStream(content.getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
private String createReason(String message) {
|
||||
return String.format("{\"message\": \"%s\"}", message);
|
||||
}
|
||||
|
||||
public static class EventListener {
|
||||
|
||||
private RestartEvent restartEvent;
|
||||
|
||||
@Subscribe(async = false)
|
||||
public void store(RestartEvent restartEvent) {
|
||||
this.restartEvent = restartEvent;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package sonia.scm.boot;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ServletContextCleanerTest {
|
||||
|
||||
@Mock
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Test
|
||||
public void testCleanup() {
|
||||
Set<String> names = ImmutableSet.of(
|
||||
"org.jboss.resteasy.Dispatcher",
|
||||
"resteasy.Deployment",
|
||||
"sonia.scm.Context",
|
||||
"org.eclipse.jetty.HttpServer",
|
||||
"javax.servlet.Context",
|
||||
"org.apache.shiro.SecurityManager"
|
||||
);
|
||||
|
||||
when(servletContext.getAttributeNames()).thenReturn(toEnumeration(names));
|
||||
|
||||
ServletContextCleaner.cleanup(servletContext);
|
||||
|
||||
verify(servletContext).removeAttribute("org.jboss.resteasy.Dispatcher");
|
||||
verify(servletContext).removeAttribute("resteasy.Deployment");
|
||||
verify(servletContext).removeAttribute("sonia.scm.Context");
|
||||
verify(servletContext, never()).removeAttribute("org.eclipse.jetty.HttpServer");
|
||||
verify(servletContext, never()).removeAttribute("javax.servlet.Context");
|
||||
verify(servletContext).removeAttribute("org.apache.shiro.SecurityManager");
|
||||
}
|
||||
|
||||
private <T> Enumeration<T> toEnumeration(Collection<T> collection) {
|
||||
return new Vector<>(collection).elements();
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* 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.junit.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()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -98,9 +98,10 @@ public class MDCFilterTest extends AbstractTestBase {
|
||||
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("127.0.0.1", chain.ctx.get(MDCFilter.MDC_CLIENT_IP));
|
||||
assertEquals("localhost", chain.ctx.get(MDCFilter.MDC_CLIENT_HOST));
|
||||
assertEquals("GET", chain.ctx.get(MDCFilter.MDC_REQUEST_METHOD));
|
||||
assertNotNull(chain.ctx.get(MDCFilter.MDC_TRANSACTION_ID));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,38 +33,38 @@ 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.Test;
|
||||
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.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserTestData;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SecurityFilter}.
|
||||
* Unit tests for {@link PropagatePrincipleFilter}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
public class SecurityFilterTest {
|
||||
public class PropagatePrincipleFilterTest {
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
@@ -83,7 +83,7 @@ public class SecurityFilterTest {
|
||||
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
private SecurityFilter securityFilter;
|
||||
private PropagatePrincipleFilter propagatePrincipleFilter;
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
@@ -94,38 +94,7 @@ public class SecurityFilterTest {
|
||||
@Before
|
||||
public void setUp(){
|
||||
this.configuration = new ScmConfiguration();
|
||||
this.securityFilter = new SecurityFilter(configuration);
|
||||
|
||||
when(request.getContextPath()).thenReturn("/scm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter on authentication endpoint v1.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoOnAuthenticationUrlV1() throws IOException, ServletException {
|
||||
checkIfAuthenticationUrlIsPassedThrough("/scm/api/auth/access_token");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests filter on authentication endpoint v2.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Test
|
||||
public void testDoOnAuthenticationUrlV2() throws IOException, ServletException {
|
||||
checkIfAuthenticationUrlIsPassedThrough("/scm/api/v2/auth/access_token");
|
||||
}
|
||||
|
||||
private void checkIfAuthenticationUrlIsPassedThrough(String uri) throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn(uri);
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
verify(request, never()).setAttribute(Mockito.anyString(), Mockito.any());
|
||||
verify(chain).doFilter(request, response);
|
||||
this.propagatePrincipleFilter = new PropagatePrincipleFilter(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,8 +105,7 @@ public class SecurityFilterTest {
|
||||
*/
|
||||
@Test
|
||||
public void testAnonymous() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
propagatePrincipleFilter.doFilter(request, response, chain);
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
@@ -149,14 +117,13 @@ public class SecurityFilterTest {
|
||||
*/
|
||||
@Test
|
||||
public void testAnonymousWithAccessEnabled() throws IOException, ServletException {
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
configuration.setAnonymousAccessEnabled(true);
|
||||
|
||||
// execute
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
propagatePrincipleFilter.doFilter(request, response, chain);
|
||||
|
||||
// verify and capture
|
||||
verify(request).setAttribute(SecurityFilter.ATTRIBUTE_REMOTE_USER, SCMContext.USER_ANONYMOUS);
|
||||
verify(request).setAttribute(PropagatePrincipleFilter.ATTRIBUTE_REMOTE_USER, SCMContext.USER_ANONYMOUS);
|
||||
verify(chain).doFilter(requestCaptor.capture(), responseCaptor.capture());
|
||||
|
||||
// assert
|
||||
@@ -173,13 +140,12 @@ public class SecurityFilterTest {
|
||||
@Test
|
||||
public void testAuthenticated() throws IOException, ServletException {
|
||||
authenticateUser(UserTestData.createTrillian());
|
||||
when(request.getRequestURI()).thenReturn("/scm/api");
|
||||
|
||||
|
||||
// execute
|
||||
securityFilter.doFilter(request, response, chain);
|
||||
propagatePrincipleFilter.doFilter(request, response, chain);
|
||||
|
||||
// verify and capture
|
||||
verify(request).setAttribute(SecurityFilter.ATTRIBUTE_REMOTE_USER, "trillian");
|
||||
verify(request).setAttribute(PropagatePrincipleFilter.ATTRIBUTE_REMOTE_USER, "trillian");
|
||||
verify(chain).doFilter(requestCaptor.capture(), responseCaptor.capture());
|
||||
|
||||
// assert
|
||||
@@ -187,42 +153,6 @@ public class SecurityFilterTest {
|
||||
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();
|
||||
@@ -236,18 +166,4 @@ public class SecurityFilterTest {
|
||||
|
||||
shiro.setSubject(subject);
|
||||
}
|
||||
|
||||
private static class AccessForbiddenSecurityFilter extends SecurityFilter {
|
||||
|
||||
private AccessForbiddenSecurityFilter(ScmConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasPermission(Subject subject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.Stage;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.io.File;
|
||||
@@ -96,14 +97,12 @@ public class DefaultUberWebResourceLoaderTest extends WebResourceLoaderTestBase
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
@Test
|
||||
public void testGetResourceFromCache() throws MalformedURLException
|
||||
{
|
||||
public void testGetResourceFromCache() {
|
||||
DefaultUberWebResourceLoader resourceLoader =
|
||||
new DefaultUberWebResourceLoader(servletContext,
|
||||
new ArrayList<PluginWrapper>());
|
||||
new ArrayList<PluginWrapper>(), Stage.PRODUCTION);
|
||||
|
||||
resourceLoader.getCache().put("/myresource", GITHUB);
|
||||
|
||||
@@ -112,6 +111,15 @@ public class DefaultUberWebResourceLoaderTest extends WebResourceLoaderTestBase
|
||||
assertSame(GITHUB, resource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetResourceCacheIsDisableInStageDevelopment() throws MalformedURLException {
|
||||
DefaultUberWebResourceLoader resourceLoader = new DefaultUberWebResourceLoader(servletContext, new ArrayList<>(), Stage.DEVELOPMENT);
|
||||
when(servletContext.getResource("/scm")).thenAnswer(invocation -> new URL("https://scm-manager.org"));
|
||||
URL url = resourceLoader.getResource("/scm");
|
||||
URL secondUrl = resourceLoader.getResource("/scm");
|
||||
assertNotSame(url, secondUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -184,7 +184,7 @@ private long calculateAverage(List<Long> times) {
|
||||
|
||||
private Repository createTestRepository(int number) {
|
||||
Repository repository = new Repository(keyGenerator.createKey(), REPOSITORY_TYPE, "namespace", "repo-" + number);
|
||||
repository.getPermissions().add(new Permission("trillian", PermissionType.READ));
|
||||
repository.addPermission(new Permission("trillian", PermissionType.READ));
|
||||
return repository;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
private String mockedNamespace = "default_namespace";
|
||||
|
||||
@Test
|
||||
public void testCreate() throws AlreadyExistsException {
|
||||
public void testCreate() {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
Repository dbRepo = manager.get(heartOfGold.getId());
|
||||
|
||||
@@ -123,18 +123,18 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
username = "unpriv"
|
||||
)
|
||||
@Test(expected = UnauthorizedException.class)
|
||||
public void testCreateWithoutPrivileges() throws AlreadyExistsException {
|
||||
public void testCreateWithoutPrivileges() {
|
||||
createTestRepository();
|
||||
}
|
||||
|
||||
@Test(expected = AlreadyExistsException.class)
|
||||
public void testCreateExisting() throws AlreadyExistsException {
|
||||
public void testCreateExisting() {
|
||||
createTestRepository();
|
||||
createTestRepository();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
public void testDelete() {
|
||||
delete(manager, createTestRepository());
|
||||
}
|
||||
|
||||
@@ -142,12 +142,12 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
username = "unpriv"
|
||||
)
|
||||
@Test(expected = UnauthorizedException.class)
|
||||
public void testDeleteWithoutPrivileges() throws Exception {
|
||||
public void testDeleteWithoutPrivileges() {
|
||||
delete(manager, createTestRepository());
|
||||
}
|
||||
|
||||
@Test(expected = RepositoryIsNotArchivedException.class)
|
||||
public void testDeleteNonArchived() throws Exception {
|
||||
public void testDeleteNonArchived() {
|
||||
configuration.setEnableRepositoryArchive(true);
|
||||
delete(manager, createTestRepository());
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteWithEnabledArchive() throws Exception {
|
||||
public void testDeleteWithEnabledArchive() {
|
||||
Repository repository = createTestRepository();
|
||||
|
||||
repository.setArchived(true);
|
||||
@@ -168,7 +168,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet() throws AlreadyExistsException {
|
||||
public void testGet() {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
String id = heartOfGold.getId();
|
||||
String description = heartOfGold.getDescription();
|
||||
@@ -186,7 +186,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
@SubjectAware(
|
||||
username = "crato"
|
||||
)
|
||||
public void testGetWithoutRequiredPrivileges() throws AlreadyExistsException {
|
||||
public void testGetWithoutRequiredPrivileges() {
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
manager.create(heartOfGold);
|
||||
|
||||
@@ -195,7 +195,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll() throws AlreadyExistsException {
|
||||
public void testGetAll() {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
Repository happyVerticalPeopleTransporter = createSecondTestRepository();
|
||||
boolean foundHeart = false;
|
||||
@@ -233,7 +233,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
@SubjectAware(username = "dent")
|
||||
public void testGetAllWithPermissionsForTwoOrThreeRepos() throws AlreadyExistsException {
|
||||
public void testGetAllWithPermissionsForTwoOrThreeRepos() {
|
||||
// mock key generator
|
||||
KeyGenerator keyGenerator = mock(KeyGenerator.class);
|
||||
Stack<String> keys = new Stack<>();
|
||||
@@ -274,7 +274,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvents() throws Exception {
|
||||
public void testEvents() {
|
||||
RepositoryManager repoManager = createRepositoryManager(false);
|
||||
repoManager.init(contextProvider);
|
||||
TestListener listener = new TestListener();
|
||||
@@ -305,7 +305,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModify() throws AlreadyExistsException {
|
||||
public void testModify() {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
|
||||
heartOfGold.setDescription("prototype ship");
|
||||
@@ -319,7 +319,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "crato")
|
||||
public void testModifyWithoutRequiredPermissions() throws AlreadyExistsException, NotFoundException {
|
||||
public void testModifyWithoutRequiredPermissions() {
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
manager.create(heartOfGold);
|
||||
heartOfGold.setDescription("prototype ship");
|
||||
@@ -334,7 +334,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefresh() throws AlreadyExistsException {
|
||||
public void testRefresh() {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
String description = heartOfGold.getDescription();
|
||||
|
||||
@@ -345,7 +345,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "crato")
|
||||
public void testRefreshWithoutRequiredPermissions() throws AlreadyExistsException, NotFoundException {
|
||||
public void testRefreshWithoutRequiredPermissions() {
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
manager.create(heartOfGold);
|
||||
heartOfGold.setDescription("prototype ship");
|
||||
@@ -354,13 +354,13 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
manager.refresh(heartOfGold);
|
||||
}
|
||||
|
||||
@Test(expected = RepositoryNotFoundException.class)
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void testRefreshNotFound(){
|
||||
manager.refresh(createRepositoryWithId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepositoryHook() throws AlreadyExistsException {
|
||||
public void testRepositoryHook() {
|
||||
CountingReceiveHook hook = new CountingReceiveHook();
|
||||
RepositoryManager repoManager = createRepositoryManager(false);
|
||||
|
||||
@@ -380,23 +380,23 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamespaceSet() throws Exception {
|
||||
public void testNamespaceSet() {
|
||||
RepositoryManager repoManager = createRepositoryManager(false);
|
||||
Repository repository = spy(createTestRepository());
|
||||
repository.setName("Testrepo");
|
||||
((DefaultRepositoryManager) repoManager).create(repository);
|
||||
repoManager.create(repository);
|
||||
assertEquals("default_namespace", repository.getNamespace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetNamespace() throws AlreadyExistsException {
|
||||
public void shouldSetNamespace() {
|
||||
Repository repository = new Repository(null, "hg", null, "scm");
|
||||
manager.create(repository);
|
||||
assertNotNull(repository.getId());
|
||||
assertNotNull(repository.getNamespace());
|
||||
}
|
||||
|
||||
private void createUriTestRepositories(RepositoryManager m) throws AlreadyExistsException {
|
||||
private void createUriTestRepositories(RepositoryManager m) {
|
||||
mockedNamespace = "namespace";
|
||||
createRepository(m, new Repository("1", "hg", "namespace", "scm"));
|
||||
createRepository(m, new Repository("2", "hg", "namespace", "scm-test"));
|
||||
@@ -452,7 +452,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
keyGenerator, repositoryDAO, handlerSet, namespaceStrategy);
|
||||
}
|
||||
|
||||
private void createRepository(RepositoryManager m, Repository repository) throws AlreadyExistsException {
|
||||
private void createRepository(RepositoryManager m, Repository repository) {
|
||||
m.create(repository);
|
||||
}
|
||||
|
||||
@@ -475,7 +475,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
assertEquals(repo.getLastModified(), other.getLastModified());
|
||||
}
|
||||
|
||||
private Repository createRepository(Repository repository) throws AlreadyExistsException {
|
||||
private Repository createRepository(Repository repository) {
|
||||
manager.create(repository);
|
||||
assertNotNull(repository.getId());
|
||||
assertNotNull(manager.get(repository.getId()));
|
||||
@@ -490,12 +490,12 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
return repository;
|
||||
}
|
||||
|
||||
private Repository createSecondTestRepository() throws AlreadyExistsException {
|
||||
private Repository createSecondTestRepository() {
|
||||
return createRepository(
|
||||
RepositoryTestData.createHappyVerticalPeopleTransporter());
|
||||
}
|
||||
|
||||
private Repository createTestRepository() throws AlreadyExistsException {
|
||||
private Repository createTestRepository() {
|
||||
return createRepository(RepositoryTestData.createHeartOfGold());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package sonia.scm.security;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import javax.ws.rs.container.ContainerRequestContext;
|
||||
import javax.ws.rs.container.ResourceInfo;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
public class SecurityRequestFilterTest {
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiroRule = new ShiroRule();
|
||||
|
||||
@Mock
|
||||
private ResourceInfo resourceInfo;
|
||||
@Mock
|
||||
private ContainerRequestContext context;
|
||||
@InjectMocks
|
||||
private SecurityRequestFilter securityRequestFilter;
|
||||
|
||||
@Test
|
||||
public void shouldAllowUnauthenticatedAccessForAnnotatedMethod() throws NoSuchMethodException {
|
||||
when(resourceInfo.getResourceMethod()).thenReturn(SecurityTestClass.class.getMethod("anonymousAccessAllowed"));
|
||||
|
||||
securityRequestFilter.filter(context);
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationException.class)
|
||||
public void shouldRejectUnauthenticatedAccessForAnnotatedMethod() throws NoSuchMethodException {
|
||||
when(resourceInfo.getResourceMethod()).thenReturn(SecurityTestClass.class.getMethod("loginRequired"));
|
||||
|
||||
securityRequestFilter.filter(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldAllowAuthenticatedAccessForMethodWithoutAnnotation() throws NoSuchMethodException {
|
||||
when(resourceInfo.getResourceMethod()).thenReturn(SecurityTestClass.class.getMethod("loginRequired"));
|
||||
|
||||
securityRequestFilter.filter(context);
|
||||
}
|
||||
|
||||
private static class SecurityTestClass {
|
||||
@AllowAnonymousAccess
|
||||
public void anonymousAccessAllowed() {
|
||||
}
|
||||
|
||||
public void loginRequired() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +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 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 SeleniumITCaseBase {
|
||||
|
||||
/**
|
||||
* Authenticates an user and call logout function.
|
||||
*/
|
||||
@Test
|
||||
public void testAuthentication() {
|
||||
MainPage main = Pages.get(driver, LoginPage.class).login("scmadmin", "scmadmin");
|
||||
assertEquals("scmadmin", main.getUserInfo());
|
||||
main.logout();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,88 +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 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 sonia.scm.repository.Repository;
|
||||
|
||||
/**
|
||||
* Repository related selenium integration tests.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class RepositoriesITCase extends SeleniumITCaseBase {
|
||||
|
||||
private MainPage main;
|
||||
|
||||
/**
|
||||
* Authenticates admin user, before each test.
|
||||
*/
|
||||
@Before
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/**
|
||||
* 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,168 +0,0 @@
|
||||
/**
|
||||
* 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();
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/**
|
||||
* 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.MoreObjects;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 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 MoreObjects.firstNonNull(displayName, type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,6 @@ import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -48,7 +47,6 @@ import org.mockito.ArgumentCaptor;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
||||
import sonia.scm.user.xml.XmlUserDAO;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@@ -57,7 +55,6 @@ import static org.mockito.Mockito.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.Rule;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -4,11 +4,11 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.PushStateDispatcher;
|
||||
import sonia.scm.repository.DefaultRepositoryProvider;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.repository.spi.HttpScmProtocol;
|
||||
@@ -58,12 +58,12 @@ public class HttpProtocolServletTest {
|
||||
private HttpScmProtocol protocol;
|
||||
|
||||
@Before
|
||||
public void init() throws RepositoryNotFoundException {
|
||||
public void init() {
|
||||
initMocks(this);
|
||||
when(userAgentParser.parse(request)).thenReturn(userAgent);
|
||||
when(userAgent.isBrowser()).thenReturn(false);
|
||||
NamespaceAndName existingRepo = new NamespaceAndName("space", "repo");
|
||||
when(serviceFactory.create(not(eq(existingRepo)))).thenThrow(RepositoryNotFoundException.class);
|
||||
when(serviceFactory.create(not(eq(existingRepo)))).thenThrow(new NotFoundException("Test", "a"));
|
||||
when(serviceFactory.create(existingRepo)).thenReturn(repositoryService);
|
||||
when(requestProvider.get()).thenReturn(httpServletRequest);
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class HttpProtocolServletTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDelegateToProvider() throws RepositoryNotFoundException, IOException, ServletException {
|
||||
public void shouldDelegateToProvider() throws IOException, ServletException {
|
||||
when(request.getPathInfo()).thenReturn("/space/name");
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName("space", "name");
|
||||
doReturn(repositoryService).when(serviceFactory).create(namespaceAndName);
|
||||
|
||||
Reference in New Issue
Block a user