From 45e48e1834e6db08e16f6c21420b9d383f4b6fc0 Mon Sep 17 00:00:00 2001 From: Johannes Schnatterer Date: Mon, 6 Aug 2018 17:00:50 +0200 Subject: [PATCH] Adds test for HgConfigInstallationsResource, its DTO and mappers. --- .../HgConfigInstallationsResource.java | 12 +- .../HgConfigInstallationsToDtoMapper.java | 21 ++-- .../HgConfigPackageCollectionToDtoMapper.java | 2 + .../HgConfigInstallationsResourceTest.java | 118 ++++++++++++++++++ .../HgConfigInstallationsToDtoMapperTest.java | 51 ++++++++ .../HgConfigPackageResourceTest.java | 4 - 6 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java create mode 100644 scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsResource.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsResource.java index e1afd8c3b2..8842d07569 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsResource.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsResource.java @@ -16,6 +16,8 @@ import javax.ws.rs.Produces; public class HgConfigInstallationsResource { + public static final String PATH_HG = "hg"; + public static final String PATH_PYTHON = "python"; private final HgConfigInstallationsToDtoMapper hgConfigInstallationsToDtoMapper; @Inject @@ -27,7 +29,7 @@ public class HgConfigInstallationsResource { * Returns the hg installations. */ @GET - @Path("hg") + @Path(PATH_HG) @Produces(HgVndMediaType.INSTALLATIONS) @TypeHint(HalRepresentation.class) @StatusCodes({ @@ -40,14 +42,15 @@ public class HgConfigInstallationsResource { ConfigurationPermissions.read(HgConfig.PERMISSION).check(); - return hgConfigInstallationsToDtoMapper.map(HgInstallerFactory.createInstaller().getHgInstallations()); + return hgConfigInstallationsToDtoMapper.map( + HgInstallerFactory.createInstaller().getHgInstallations(), PATH_HG); } /** * Returns the python installations. */ @GET - @Path("python") + @Path(PATH_PYTHON) @Produces(HgVndMediaType.INSTALLATIONS) @TypeHint(HalRepresentation.class) @StatusCodes({ @@ -60,6 +63,7 @@ public class HgConfigInstallationsResource { ConfigurationPermissions.read(HgConfig.PERMISSION).check(); - return hgConfigInstallationsToDtoMapper.map(HgInstallerFactory.createInstaller().getPythonInstallations()); + return hgConfigInstallationsToDtoMapper.map( + HgInstallerFactory.createInstaller().getPythonInstallations(), PATH_PYTHON); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java index 767c05abbe..575166c007 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapper.java @@ -1,21 +1,26 @@ package sonia.scm.api.v2.resources; -import de.otto.edison.hal.HalRepresentation; +import com.google.inject.Inject; -import javax.inject.Inject; import java.util.List; import static de.otto.edison.hal.Links.linkingTo; public class HgConfigInstallationsToDtoMapper { - @Inject private UriInfoStore uriInfoStore; - public HalRepresentation map(List installations) { - return new HgConfigInstallationsDto(linkingTo().self(createSelfLink()).build(), installations); + private UriInfoStore uriInfoStore; + + @Inject + public HgConfigInstallationsToDtoMapper(UriInfoStore uriInfoStore, String path) { + this.uriInfoStore = uriInfoStore; } - private String createSelfLink() { - LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), HgConfigInstallationsResource.class); - return linkBuilder.method("get").parameters().href(); + public HgConfigInstallationsDto map(List installations, String path) { + return new HgConfigInstallationsDto(linkingTo().self(createSelfLink(path)).build(), installations); + } + + private String createSelfLink(String path) { + LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), HgConfigResource.class); + return linkBuilder.method("getInstallationsResource").parameters().href() + '/' + path; } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackageCollectionToDtoMapper.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackageCollectionToDtoMapper.java index 5e69c8b199..46f4526aa4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackageCollectionToDtoMapper.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/api/v2/resources/HgConfigPackageCollectionToDtoMapper.java @@ -4,6 +4,8 @@ import sonia.scm.installer.HgPackage; import javax.inject.Inject; +// TODO could this be simplified similar to HgConfigInstallationsToDtoMapper? +// That is, do we really need the packages as _embedded list? public class HgConfigPackageCollectionToDtoMapper extends CollectionToDtoMapper { static final String COLLECTION_NAME = "packages"; diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java new file mode 100644 index 0000000000..f2fe4165f9 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsResourceTest.java @@ -0,0 +1,118 @@ +package sonia.scm.api.v2.resources; + +import com.github.sdorra.shiro.ShiroRule; +import com.github.sdorra.shiro.SubjectAware; +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.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import javax.inject.Provider; +import javax.servlet.http.HttpServletResponse; +import java.net.URI; +import java.net.URISyntaxException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +@SubjectAware( + configuration = "classpath:sonia/scm/configuration/shiro.ini", + password = "secret" +) +@RunWith(MockitoJUnitRunner.class) +public class HgConfigInstallationsResourceTest { + + @Rule + public ShiroRule shiro = new ShiroRule(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + + private final URI baseUri = URI.create("/"); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private UriInfoStore uriInfoStore; + + @InjectMocks + private HgConfigInstallationsToDtoMapper mapper; + + @Mock + private Provider resourceProvider; + + + @Before + public void prepareEnvironment() { + HgConfigInstallationsResource resource = new HgConfigInstallationsResource(mapper); + + when(resourceProvider.get()).thenReturn(resource); + dispatcher.getRegistry().addSingletonResource( + new HgConfigResource(null, null, null, null, + null, resourceProvider)); + + when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + } + + @Test + @SubjectAware(username = "readOnly") + public void shouldGetHgInstallations() throws Exception { + MockHttpResponse response = get("hg"); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + + String contentAsString = response.getContentAsString(); + assertThat(contentAsString).contains("{\"paths\":["); + assertThat(contentAsString).contains("hg"); + assertThat(contentAsString).doesNotContain("python"); + + assertThat(contentAsString).contains("\"self\":{\"href\":\"/v2/config/hg/installations/hg"); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldGetHgInstallationsOnlyWhenAuthorized() throws Exception { + thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + + get("hg"); + } + + @Test + @SubjectAware(username = "readOnly") + public void shouldGetPythonInstallations() throws Exception { + MockHttpResponse response = get("python"); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + + String contentAsString = response.getContentAsString(); + assertThat(contentAsString).contains("{\"paths\":["); + assertThat(contentAsString).contains("python"); + + assertThat(contentAsString).contains("\"self\":{\"href\":\"/v2/config/hg/installations/python"); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldGetPythonInstallationsOnlyWhenAuthorized() throws Exception { + thrown.expectMessage("Subject does not have permission [configuration:read:hg]"); + + get("python"); + } + + private MockHttpResponse get(String path) throws URISyntaxException { + MockHttpRequest request = MockHttpRequest.get("/" + HgConfigResource.HG_CONFIG_PATH_V2 + "/installations/" + path); + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + return response; + } +} diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java new file mode 100644 index 0000000000..34048f80b2 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigInstallationsToDtoMapperTest.java @@ -0,0 +1,51 @@ +package sonia.scm.api.v2.resources; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class HgConfigInstallationsToDtoMapperTest { + + + private URI baseUri = URI.create("http://example.com/base/"); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private UriInfoStore uriInfoStore; + + @InjectMocks + private HgConfigInstallationsToDtoMapper mapper; + + private URI expectedBaseUri; + + private String expectedPath = "path"; + + @Before + public void init() { + when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2 + "/installations/" + expectedPath); + } + + @Test + public void shouldMapFields() { + List installations = Arrays.asList("/hg", "/bin/hg"); + + HgConfigInstallationsDto dto = mapper.map(installations, expectedPath); + + assertThat(dto.getPaths()).isEqualTo(installations); + + assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("self").get().getHref()); + } +} diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java index 0bb7d3e048..5c0fc65e26 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/api/v2/resources/HgConfigPackageResourceTest.java @@ -13,7 +13,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.InjectMocks; @@ -53,9 +52,6 @@ public class HgConfigPackageResourceTest { @Rule public ExpectedException thrown = ExpectedException.none(); - @Rule - public TemporaryFolder folder= new TemporaryFolder(); - private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); private final URI baseUri = java.net.URI.create("/");