Enable plugin management via CLI (#2087)

Co-authored-by: Konstantin Schaper <konstantin.schaper@cloudogu.com>
This commit is contained in:
Eduard Heimbuch
2022-07-19 09:02:00 +02:00
committed by GitHub
parent 67c083ee54
commit fc28da90b3
27 changed files with 1718 additions and 74 deletions

View File

@@ -43,6 +43,7 @@ import sonia.scm.plugin.AvailablePlugin;
import sonia.scm.plugin.AvailablePluginDescriptor;
import sonia.scm.plugin.InstalledPlugin;
import sonia.scm.plugin.InstalledPluginDescriptor;
import sonia.scm.plugin.PendingPlugins;
import sonia.scm.plugin.PluginInformation;
import sonia.scm.plugin.PluginManager;
import sonia.scm.web.RestDispatcher;
@@ -65,7 +66,7 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class PendingPluginResourceTest {
private RestDispatcher dispatcher = new RestDispatcher();
private final RestDispatcher dispatcher = new RestDispatcher();
@SuppressWarnings("unused")
ResourceLinks resourceLinks = ResourceLinksMock.createMock(create("/"));
@@ -125,23 +126,22 @@ class PendingPluginResourceTest {
@Test
void shouldGetEmptyPluginListsWithoutInstallLinkWhenNoPendingPluginsPresent() throws URISyntaxException, UnsupportedEncodingException {
AvailablePlugin availablePlugin = createAvailablePlugin("not-pending-plugin");
when(availablePlugin.isPending()).thenReturn(false);
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pluginManager.getPending()).thenReturn(pendingPlugins);
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
assertThat(response.getContentAsString()).contains("\"_links\":{\"self\":{\"href\":\"/v2/plugins/pending\"}}");
assertThat(response.getContentAsString()).doesNotContain("not-pending-plugin");
}
@Test
void shouldGetPendingAvailablePluginListWithInstallAndCancelLink() throws URISyntaxException, UnsupportedEncodingException {
AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin");
when(availablePlugin.isPending()).thenReturn(true);
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pluginManager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.getInstall()).thenReturn(singletonList(availablePlugin));
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);
@@ -155,10 +155,11 @@ class PendingPluginResourceTest {
@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));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pluginManager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.getUpdate()).thenReturn(singletonList(installedPlugin));
when(pendingPlugins.getInstall()).thenReturn(singletonList(availablePlugin));
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);
@@ -170,10 +171,10 @@ class PendingPluginResourceTest {
@Test
void shouldGetPendingUninstallPluginListWithInstallLink() throws URISyntaxException, UnsupportedEncodingException {
when(pluginManager.getAvailable()).thenReturn(emptyList());
InstalledPlugin installedPlugin = createInstalledPlugin("uninstalled-plugin");
when(installedPlugin.isMarkedForUninstall()).thenReturn(true);
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pendingPlugins.getUninstall()).thenReturn(singletonList(installedPlugin));
when(pluginManager.getPending()).thenReturn(pendingPlugins);
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);
@@ -187,10 +188,10 @@ class PendingPluginResourceTest {
void shouldNotReturnExecuteLinkIfRestartIsNotSupported() throws URISyntaxException, UnsupportedEncodingException {
when(restarter.isSupported()).thenReturn(false);
when(pluginManager.getAvailable()).thenReturn(emptyList());
InstalledPlugin installedPlugin = createInstalledPlugin("uninstalled-plugin");
when(installedPlugin.isMarkedForUninstall()).thenReturn(true);
when(pluginManager.getInstalled()).thenReturn(singletonList(installedPlugin));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pluginManager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.getUninstall()).thenReturn(singletonList(installedPlugin));
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);
@@ -239,8 +240,9 @@ class PendingPluginResourceTest {
@Test
void shouldGetPendingAvailablePluginListWithoutInstallAndCancelLink() throws URISyntaxException, UnsupportedEncodingException {
AvailablePlugin availablePlugin = createAvailablePlugin("pending-available-plugin");
when(availablePlugin.isPending()).thenReturn(true);
when(pluginManager.getAvailable()).thenReturn(singletonList(availablePlugin));
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(pluginManager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.getInstall()).thenReturn(singletonList(availablePlugin));
MockHttpRequest request = MockHttpRequest.get("/v2/plugins/pending");
dispatcher.invoke(request, response);

View File

@@ -108,7 +108,7 @@ public class TemplateTestRenderer {
return templateEngineFactory;
}
public CommandLine.Model.CommandSpec getMockedSpeck() {
public CommandLine.Model.CommandSpec getMockedSpec() {
ResourceBundle resourceBundle = getResourceBundle();
CommandLine.Model.CommandSpec mock = mock(CommandLine.Model.CommandSpec.class);
lenient().when(mock.resourceBundle()).thenReturn(resourceBundle);

View File

@@ -51,7 +51,7 @@ class GroupListCommandTest {
@BeforeEach
void initCommand() {
command = new GroupListCommand(testRenderer.createTemplateRenderer(), manager, beanMapper);
command.setSpec(testRenderer.getMockedSpeck());
command.setSpec(testRenderer.getMockedSpec());
}
@BeforeEach

View File

@@ -0,0 +1,118 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PluginManager;
import sonia.scm.plugin.PluginTestHelper;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class PluginAddCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager manager;
@InjectMocks
private PluginAddCommand command;
@Test
void shouldAddPlugin() {
String pluginName = "scm-test-plugin";
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
doReturn(Optional.of(PluginTestHelper.createAvailable(pluginName))).when(manager).getAvailable(pluginName);
command.setName(pluginName);
command.run();
verify(manager).install(pluginName, false);
verify(templateRenderer).renderPluginAdded(pluginName);
verify(templateRenderer).renderServerRestartRequired();
}
@Test
void shouldAddPluginWithRestart() {
String pluginName = "scm-test-plugin";
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
doReturn(Optional.of(PluginTestHelper.createAvailable(pluginName))).when(manager).getAvailable(pluginName);
command.setName(pluginName);
command.setApply(true);
command.run();
verify(manager).install(pluginName, true);
verify(templateRenderer).renderPluginAdded(pluginName);
verify(templateRenderer).renderServerRestartTriggered();
}
@Test
void shouldRenderErrorIfPluginAlreadyInstalled() {
String pluginName = "scm-test-plugin";
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
command.setName(pluginName);
command.run();
verify(templateRenderer).renderPluginAlreadyInstalledError();
}
@Test
void shouldRenderErrorIfPluginNotAvailable() {
String pluginName = "scm-test-plugin";
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
doReturn(Optional.empty()).when(manager).getAvailable(pluginName);
command.setName(pluginName);
command.run();
verify(templateRenderer).renderPluginNotAvailableError();
}
@Test
void shouldRenderErrorIfPluginInstallationFailed() {
String pluginName = "scm-test-plugin";
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
doReturn(Optional.of(PluginTestHelper.createAvailable(pluginName))).when(manager).getAvailable(pluginName);
doThrow(RuntimeException.class).when(manager).install(pluginName, false);
command.setName(pluginName);
assertThrows(RuntimeException.class, () -> command.run());
verify(templateRenderer).renderPluginCouldNotBeAdded(pluginName);
}
}

View File

@@ -0,0 +1,84 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PendingPlugins;
import sonia.scm.plugin.PluginManager;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class PluginApplyCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager manager;
@InjectMocks
private PluginApplyCommand command;
@Test
void shouldRestartServer() {
command.setRestart(true);
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(manager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.existPendingChanges()).thenReturn(true);
command.run();
verify(manager).executePendingAndRestart();
verify(templateRenderer).renderServerRestartTriggered();
}
@Test
void shouldNotRestartServerIfFlagIsMissing() {
command.run();
verify(manager, never()).executePendingAndRestart();
verify(templateRenderer).renderConfirmServerRestart();
}
@Test
void shouldNotRestartServerIfNoPendingChanges() {
command.setRestart(true);
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(manager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.existPendingChanges()).thenReturn(false);
command.run();
verify(manager, never()).executePendingAndRestart();
verify(templateRenderer).renderSkipServerRestart();
}
}

View File

@@ -0,0 +1,89 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.cli.TemplateTestRenderer;
import sonia.scm.plugin.PendingPlugins;
import sonia.scm.plugin.PluginManager;
import sonia.scm.plugin.PluginTestHelper;
import static java.util.List.of;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
class PluginListCommandTest {
private final TemplateTestRenderer templateTestRenderer = new TemplateTestRenderer();
@Mock
private PluginManager manager;
private PluginListCommand command;
@BeforeEach
void initCommand() {
command = new PluginListCommand(templateTestRenderer.createTemplateRenderer(), manager);
command.setSpec(templateTestRenderer.getMockedSpec());
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
doReturn(pendingPlugins).when(manager).getPending();
}
@Test
void shouldListPlugins() {
doReturn(of(PluginTestHelper.createInstalled("scm-test-plugin"))).when(manager).getInstalled();
doReturn(of(
PluginTestHelper.createAvailable("scm-review-plugin"),
PluginTestHelper.createAvailable("scm-test-plugin", "1.1.0"))
).when(manager).getAvailable();
command.run();
assertThat(templateTestRenderer.getStdOut())
.contains("NAME DISPLAY NAME AVAILABLE INSTALLED PENDING?")
.contains("scm-review-plugin 1.0")
.contains("scm-test-plugin 1.1.0 1.0");
}
@Test
void shouldListPluginsAsShortList() {
doReturn(of(PluginTestHelper.createInstalled("scm-test-plugin"), PluginTestHelper.createInstalled("scm-archive-plugin"))).when(manager).getInstalled();
doReturn(of(
PluginTestHelper.createAvailable("scm-review-plugin"),
PluginTestHelper.createAvailable("scm-test-plugin", "1.1.0"))
).when(manager).getAvailable();
command.setUseShortTemplate(true);
command.run();
assertThat(templateTestRenderer.getStdOut())
.isEqualTo("scm-archive-plugin\nscm-review-plugin\nscm-test-plugin\n");
}
}

View File

@@ -0,0 +1,107 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PluginManager;
import sonia.scm.plugin.PluginTestHelper;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class PluginRemoveCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager manager;
@InjectMocks
private PluginRemoveCommand command;
@Test
void shouldRemovePlugin() {
String pluginName = "scm-test-plugin";
command.setName(pluginName);
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
command.run();
verify(manager).uninstall(pluginName, false);
verify(templateRenderer).renderPluginRemoved(pluginName);
verify(templateRenderer).renderServerRestartRequired();
}
@Test
void shouldRemovePluginWithRestart() {
String pluginName = "scm-test-plugin";
command.setName(pluginName);
command.setApply(true);
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
command.run();
verify(manager).uninstall(pluginName, true);
verify(templateRenderer).renderPluginRemoved(pluginName);
verify(templateRenderer).renderServerRestartTriggered();
}
@Test
void shouldRenderErrorIfPluginNotInstalled() {
String pluginName = "scm-test-plugin";
command.setName(pluginName);
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
command.run();
verify(manager, never()).uninstall(eq(pluginName), anyBoolean());
verify(templateRenderer).renderPluginNotInstalledError();
}
@Test
void shouldRenderErrorIfPluginCouldNotBeRemoved() {
String pluginName = "scm-test-plugin";
command.setName(pluginName);
doThrow(RuntimeException.class).when(manager).uninstall(pluginName, false);
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
assertThrows(RuntimeException.class, () -> command.run());
verify(templateRenderer).renderPluginCouldNotBeRemoved(pluginName);
}
}

View File

@@ -0,0 +1,74 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PendingPlugins;
import sonia.scm.plugin.PluginManager;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class PluginResetChangesCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager manager;
@InjectMocks
private PluginResetChangesCommand command;
@Test
void shouldCancelPendingPlugins() {
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(manager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.existPendingChanges()).thenReturn(true);
command.run();
verify(manager).cancelPending();
verify(templateRenderer).renderPluginsReseted();
}
@Test
void shouldRenderErrorIfNoPendingPlugins() {
PendingPlugins pendingPlugins = mock(PendingPlugins.class);
when(manager.getPending()).thenReturn(pendingPlugins);
when(pendingPlugins.existPendingChanges()).thenReturn(false);
command.run();
verify(manager, never()).cancelPending();
verify(templateRenderer).renderNoPendingPlugins();
}
}

View File

@@ -0,0 +1,79 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PluginManager;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class PluginUpdateAllCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager pluginManager;
@InjectMocks
private PluginUpdateAllCommand command;
@Test
void shouldUpdateAll() {
command.run();
verify(pluginManager).updateAll();
verify(templateRenderer).renderAllPluginsUpdated();
verify(templateRenderer).renderServerRestartRequired();
}
@Test
void shouldUpdateAllWithRestart() {
command.setApply(true);
command.run();
verify(pluginManager).updateAll();
verify(pluginManager).executePendingAndRestart();
verify(templateRenderer).renderAllPluginsUpdated();
verify(templateRenderer).renderServerRestartTriggered();
}
@Test
void shouldRenderErrorIfUpdateFailed() {
doThrow(RuntimeException.class).when(pluginManager).updateAll();
assertThrows(RuntimeException.class, () -> command.run());
verify(templateRenderer).renderPluginsUpdateError();
}
}

View File

@@ -0,0 +1,114 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.plugin.cli;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.plugin.PluginManager;
import sonia.scm.plugin.PluginTestHelper;
import java.util.Optional;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class PluginUpdateCommandTest {
@Mock
private PluginTemplateRenderer templateRenderer;
@Mock
private PluginManager manager;
@InjectMocks
private PluginUpdateCommand command;
@Test
void shouldUpdateSinglePlugin() {
String pluginName = "scm-test-plugin";
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
doReturn(singletonList(PluginTestHelper.createInstalled(pluginName))).when(manager).getUpdatable();
command.setName(pluginName);
command.run();
verify(manager).install(pluginName, false);
verify(templateRenderer).renderPluginUpdated(pluginName);
verify(templateRenderer).renderServerRestartRequired();
}
@Test
void shouldUpdateSinglePluginWithRestart() {
String pluginName = "scm-test-plugin";
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
doReturn(singletonList(PluginTestHelper.createInstalled(pluginName))).when(manager).getUpdatable();
command.setName(pluginName);
command.setApply(true);
command.run();
verify(manager).install(pluginName, true);
verify(templateRenderer).renderPluginUpdated(pluginName);
verify(templateRenderer).renderServerRestartTriggered();
}
@Test
void shouldRenderErrorIfPluginNotInstalled() {
String pluginName = "scm-test-plugin";
doReturn(Optional.empty()).when(manager).getInstalled(pluginName);
command.setName(pluginName);
command.run();
verify(manager, never()).install(eq(pluginName), anyBoolean());
verify(templateRenderer).renderPluginNotInstalledError();
}
@Test
void shouldRenderErrorIfPluginNotUpdatable() {
String pluginName = "scm-test-plugin";
doReturn(Optional.of(PluginTestHelper.createInstalled(pluginName))).when(manager).getInstalled(pluginName);
doReturn(emptyList()).when(manager).getUpdatable();
command.setName(pluginName);
command.run();
verify(manager, never()).install(eq(pluginName), anyBoolean());
verify(templateRenderer).renderPluginNotUpdatable(pluginName);
}
}

View File

@@ -69,7 +69,7 @@ class UserListCommandTest {
@Test
void shouldRenderShortTableInEnglish() {
testRenderer.setLocale("en");
command.setSpec(testRenderer.getMockedSpeck());
command.setSpec(testRenderer.getMockedSpec());
command.setUseShortTemplate(true);
command.run();
@@ -81,7 +81,7 @@ class UserListCommandTest {
@Test
void shouldRenderShortTableInGerman() {
testRenderer.setLocale("de");
command.setSpec(testRenderer.getMockedSpeck());
command.setSpec(testRenderer.getMockedSpec());
command.setUseShortTemplate(true);
command.run();
@@ -93,7 +93,7 @@ class UserListCommandTest {
@Test
void shouldRenderLongTableInEnglish() {
testRenderer.setLocale("en");
command.setSpec(testRenderer.getMockedSpeck());
command.setSpec(testRenderer.getMockedSpec());
command.run();
@@ -107,7 +107,7 @@ class UserListCommandTest {
@Test
void shouldRenderLongTableInGerman() {
testRenderer.setLocale("de");
command.setSpec(testRenderer.getMockedSpeck());
command.setSpec(testRenderer.getMockedSpec());
command.run();