From 2e42d8be915db7601651216eb73964fe48f73ba5 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Fri, 13 Sep 2019 14:44:32 +0200 Subject: [PATCH] Return pending plugins in endpoint --- .../v2/resources/PendingPluginResource.java | 30 +++++++++- .../resources/PendingPluginResourceTest.java | 55 +++++++++++++++---- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java index c9d9982ccc..47e3d2f9f6 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java @@ -6,6 +6,7 @@ import de.otto.edison.hal.Embedded; import de.otto.edison.hal.HalRepresentation; import de.otto.edison.hal.Links; import sonia.scm.plugin.AvailablePlugin; +import sonia.scm.plugin.InstalledPlugin; import sonia.scm.plugin.PluginManager; import sonia.scm.plugin.PluginPermissions; import sonia.scm.web.VndMediaType; @@ -16,7 +17,9 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; +import java.util.Collection; import java.util.List; +import java.util.stream.Stream; import static de.otto.edison.hal.Link.link; import static de.otto.edison.hal.Links.linkingTo; @@ -50,6 +53,14 @@ public class PendingPluginResource { .stream() .filter(AvailablePlugin::isPending) .collect(toList()); + List installed = pluginManager.getInstalled(); + + Stream newPlugins = pending + .stream() + .filter(a -> !contains(installed, a)); + Stream updatePlugins = installed + .stream() + .filter(i -> contains(pending, i)); Links.Builder linksBuilder = linkingTo().self(resourceLinks.pendingPluginCollection().self()); @@ -58,11 +69,28 @@ public class PendingPluginResource { } Embedded.Builder embedded = Embedded.embeddedBuilder(); - embedded.with("available", pending.stream().map(mapper::mapAvailable).collect(toList())); + embedded.with("new", newPlugins.map(mapper::mapAvailable).collect(toList())); + embedded.with("update", updatePlugins.map(i -> mapper.mapInstalled(i, pending)).collect(toList())); return Response.ok(new HalRepresentation(linksBuilder.build(), embedded.build())).build(); } + private boolean contains(Collection installedPlugins, AvailablePlugin availablePlugin) { + return installedPlugins + .stream() + .anyMatch(installedPlugin -> haveSameName(installedPlugin, availablePlugin)); + } + + private boolean contains(Collection availablePlugins, InstalledPlugin installedPlugin) { + return availablePlugins + .stream() + .anyMatch(availablePlugin -> haveSameName(installedPlugin, availablePlugin)); + } + + private boolean haveSameName(InstalledPlugin installedPlugin, AvailablePlugin availablePlugin) { + return installedPlugin.getDescriptor().getInformation().getName().equals(availablePlugin.getDescriptor().getInformation().getName()); + } + @POST @Path("/install") @StatusCodes({ diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java index 065ff9d723..d4b8a5bf5a 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/PendingPluginResourceTest.java @@ -18,7 +18,8 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.plugin.AvailablePlugin; import sonia.scm.plugin.AvailablePluginDescriptor; -import sonia.scm.plugin.PluginCondition; +import sonia.scm.plugin.InstalledPlugin; +import sonia.scm.plugin.InstalledPluginDescriptor; import sonia.scm.plugin.PluginInformation; import sonia.scm.plugin.PluginManager; @@ -27,7 +28,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; -import java.util.Collections; import static java.net.URI.create; import static java.util.Collections.singletonList; @@ -76,6 +76,11 @@ class PendingPluginResourceTest { dto.setName(((AvailablePlugin)invocation.getArgument(0)).getDescriptor().getInformation().getName()); return dto; }); + lenient().when(mapper.mapInstalled(any(), any())).thenAnswer(invocation -> { + PluginDto dto = new PluginDto(); + dto.setName(((InstalledPlugin)invocation.getArgument(0)).getDescriptor().getInformation().getName()); + return dto; + }); } @Nested @@ -94,7 +99,7 @@ class PendingPluginResourceTest { @Test void shouldGetEmptyPluginListsWithoutInstallLinkWhenNoPendingPluginsPresent() throws URISyntaxException, UnsupportedEncodingException { - AvailablePlugin availablePlugin = createAvailablePlugin("not-available-plugin"); + AvailablePlugin availablePlugin = createAvailablePlugin("not-pending-plugin"); when(availablePlugin.isPending()).thenReturn(false); when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin)); @@ -103,12 +108,12 @@ class PendingPluginResourceTest { assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); assertThat(response.getContentAsString()).contains("\"_links\":{\"self\":{\"href\":\"/v2/plugins/pending\"}}"); - assertThat(response.getContentAsString()).doesNotContain("not-available-plugin"); + assertThat(response.getContentAsString()).doesNotContain("not-pending-plugin"); } @Test - void shouldGetPendingAvailablePluginListsWithInstallLink() throws URISyntaxException, UnsupportedEncodingException { - AvailablePlugin availablePlugin = createAvailablePlugin("available-plugin"); + void shouldGetPendingAvailablePluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException { + AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin"); when(availablePlugin.isPending()).thenReturn(true); when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin)); @@ -116,7 +121,24 @@ class PendingPluginResourceTest { dispatcher.invoke(request, response); assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); - assertThat(response.getContentAsString()).contains("\"_embedded\":{\"available\":[{\"name\":\"available-plugin\""); + assertThat(response.getContentAsString()).contains("\"new\":[{\"name\":\"pending-available-plugin\""); + assertThat(response.getContentAsString()).contains("\"install\":{\"href\":\"/v2/plugins/pending/install\"}"); + System.out.println(response.getContentAsString()); + } + + @Test + void shouldGetPendingUpdatePluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException { + AvailablePlugin availablePlugin = createAvailablePlugin("available-plugin"); + when(availablePlugin.isPending()).thenReturn(true); + when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin)); + InstalledPlugin installedPlugin = createInstalledPlugin("available-plugin"); + when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin)); + + MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending"); + dispatcher.invoke(request, response); + + assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK); + assertThat(response.getContentAsString()).contains("\"update\":[{\"name\":\"available-plugin\""); assertThat(response.getContentAsString()).contains("\"install\":{\"href\":\"/v2/plugins/pending/install\"}"); System.out.println(response.getContentAsString()); } @@ -182,11 +204,24 @@ class PendingPluginResourceTest { } private AvailablePlugin createAvailablePlugin(PluginInformation pluginInformation) { - AvailablePluginDescriptor descriptor = new AvailablePluginDescriptor( - pluginInformation, new PluginCondition(), Collections.emptySet(), "https://download.hitchhiker.com", null - ); + AvailablePluginDescriptor descriptor = mock(AvailablePluginDescriptor.class); + lenient().when(descriptor.getInformation()).thenReturn(pluginInformation); AvailablePlugin availablePlugin = mock(AvailablePlugin.class); lenient().when(availablePlugin.getDescriptor()).thenReturn(descriptor); return availablePlugin; } + + private InstalledPlugin createInstalledPlugin(String name) { + PluginInformation pluginInformation = new PluginInformation(); + pluginInformation.setName(name); + return createInstalledPlugin(pluginInformation); + } + + private InstalledPlugin createInstalledPlugin(PluginInformation pluginInformation) { + InstalledPluginDescriptor descriptor = mock(InstalledPluginDescriptor.class); + lenient().when(descriptor.getInformation()).thenReturn(pluginInformation); + InstalledPlugin installedPlugin = mock(InstalledPlugin.class); + lenient().when(installedPlugin.getDescriptor()).thenReturn(descriptor); + return installedPlugin; + } }