From: Julien Lancelot Date: Mon, 12 Feb 2018 11:03:26 +0000 (+0100) Subject: SONAR-8964 Drop overall notifications not related to the current user on SonarCloud X-Git-Tag: 7.5~1664 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4a85b3c8960f0e448319ffbe8de894e0146ff5a5;p=sonarqube.git SONAR-8964 Drop overall notifications not related to the current user on SonarCloud * SONAR-8964 Remove some global notifications in api/notifications/list on SonarCloud * SONAR-8964 Remove some global notifications in api/notifications/add on SonarCloud * In WebServiceEngine, define web services in start() * SONAR-8964 Remove some global notifications in api/notifications/remove on SonarCloud * Move some user ITs to their own suite * SONAR-8964 Add ITs on notifications (not for SonarCloud) * SONAR-8964 Add ITs on notifications for SonarCloud --- diff --git a/cix.sh b/cix.sh index 2d2b0b50f71..715a27db7c9 100755 --- a/cix.sh +++ b/cix.sh @@ -43,7 +43,7 @@ case "$RUN_ACTIVITY" in ;; Category4) - CATEGORY="Category4|duplication" + CATEGORY="Category4|duplication|user" ;; Category5) diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java index 896728af4e3..b2ada687dad 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/AddAction.java @@ -42,34 +42,30 @@ import org.sonar.server.ws.KeyExamples; import static java.util.Optional.empty; import static org.sonar.core.util.Protobuf.setNullable; -import static org.sonar.core.util.stream.MoreCollectors.toList; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; -import static org.sonar.server.ws.WsUtils.checkFound; -import static org.sonar.server.ws.WsUtils.checkRequest; import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_ADD; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_TYPE; +import static org.sonar.server.ws.WsUtils.checkFound; +import static org.sonar.server.ws.WsUtils.checkRequest; public class AddAction implements NotificationsWsAction { private final NotificationCenter notificationCenter; private final NotificationUpdater notificationUpdater; + private final Dispatchers dispatchers; private final DbClient dbClient; private final ComponentFinder componentFinder; private final UserSession userSession; - private final List globalDispatchers; - private final List projectDispatchers; - public AddAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) { + public AddAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, Dispatchers dispatchers, DbClient dbClient, ComponentFinder componentFinder, + UserSession userSession) { this.notificationCenter = notificationCenter; this.notificationUpdater = notificationUpdater; + this.dispatchers = dispatchers; this.dbClient = dbClient; this.componentFinder = componentFinder; this.userSession = userSession; - this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(toList()); - this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(toList()); } @Override @@ -101,8 +97,8 @@ public class AddAction implements NotificationsWsAction { "
  • Global notifications: %s
  • " + "
  • Per project notifications: %s
  • " + "", - String.join(", ", globalDispatchers), - String.join(", ", projectDispatchers)) + String.join(", ", dispatchers.getGlobalDispatchers()), + String.join(", ", dispatchers.getProjectDispatchers())) .setRequired(true) .setExampleValue(MyNewIssuesNotificationDispatcher.KEY); @@ -158,15 +154,15 @@ public class AddAction implements NotificationsWsAction { setNullable(request.param(PARAM_LOGIN), add::setLogin); if (add.getProject() == null) { - checkRequest(globalDispatchers.contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s", + checkRequest(dispatchers.getGlobalDispatchers().contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s", PARAM_TYPE, add.getType(), - globalDispatchers); + dispatchers.getGlobalDispatchers()); } else { - checkRequest(projectDispatchers.contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s", + checkRequest(dispatchers.getProjectDispatchers().contains(add.getType()), "Value of parameter '%s' (%s) must be one of: %s", PARAM_TYPE, add.getType(), - projectDispatchers); + dispatchers.getProjectDispatchers()); } return add; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/Dispatchers.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/Dispatchers.java new file mode 100644 index 00000000000..b96959e3821 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/Dispatchers.java @@ -0,0 +1,30 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.notification.ws; + +import java.util.List; + +public interface Dispatchers { + + List getGlobalDispatchers(); + + List getProjectDispatchers(); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/DispatchersImpl.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/DispatchersImpl.java new file mode 100644 index 00000000000..4032e1847c9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/DispatchersImpl.java @@ -0,0 +1,89 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.notification.ws; + +import com.google.common.collect.ImmutableSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import org.sonar.api.Startable; +import org.sonar.api.config.Configuration; +import org.sonar.process.ProcessProperties; +import org.sonar.server.event.NewAlerts; +import org.sonar.server.issue.notification.DoNotFixNotificationDispatcher; +import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher; +import org.sonar.server.notification.NotificationCenter; + +import static org.sonar.core.util.stream.MoreCollectors.toList; +import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; +import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; + +public class DispatchersImpl implements Dispatchers, Startable { + + private static final Set GLOBAL_DISPATCHERS_TO_IGNORE_ON_SONAR_CLOUD = ImmutableSet.of( + NewAlerts.KEY, + DoNotFixNotificationDispatcher.KEY, + NewIssuesNotificationDispatcher.KEY); + + private final NotificationCenter notificationCenter; + private final Configuration configuration; + + private List projectDispatchers; + private List globalDispatchers; + + public DispatchersImpl(NotificationCenter notificationCenter, Configuration configuration) { + this.notificationCenter = notificationCenter; + this.configuration = configuration; + } + + @Override + public List getGlobalDispatchers() { + return globalDispatchers; + } + + @Override + public List getProjectDispatchers() { + return projectDispatchers; + } + + @Override + public void start() { + boolean isOnSonarCloud = configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false); + this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true") + .stream() + .filter(filterDispatcherForSonarCloud(isOnSonarCloud)) + .sorted() + .collect(toList()); + this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true") + .stream() + .sorted() + .collect(toList()); + } + + private static Predicate filterDispatcherForSonarCloud(boolean isOnSonarCloud) { + return dispatcher -> !(isOnSonarCloud && GLOBAL_DISPATCHERS_TO_IGNORE_ON_SONAR_CLOUD.contains(dispatcher)); + } + + @Override + public void stop() { + // nothing to do + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/ListAction.java index e7c5c60afe5..9f15c5e64ac 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/ListAction.java @@ -53,28 +53,25 @@ import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.core.util.stream.MoreCollectors.toOneElement; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; -import static org.sonar.server.ws.WsUtils.checkFound; -import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_LIST; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN; +import static org.sonar.server.ws.WsUtils.checkFound; +import static org.sonar.server.ws.WsUtils.writeProtobuf; public class ListAction implements NotificationsWsAction { + private static final Splitter PROPERTY_KEY_SPLITTER = Splitter.on("."); private final DbClient dbClient; private final UserSession userSession; - private final List globalDispatchers; - private final List perProjectDispatchers; private final List channels; + private final Dispatchers dispatchers; - public ListAction(NotificationCenter notificationCenter, DbClient dbClient, UserSession userSession) { + public ListAction(NotificationCenter notificationCenter, DbClient dbClient, UserSession userSession, Dispatchers dispatchers) { this.dbClient = dbClient; this.userSession = userSession; - this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList()); - this.perProjectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true").stream().sorted().collect(MoreCollectors.toList()); this.channels = notificationCenter.getChannels().stream().map(NotificationChannel::getKey).sorted().collect(MoreCollectors.toList()); + this.dispatchers = dispatchers; } @Override @@ -110,8 +107,8 @@ public class ListAction implements NotificationsWsAction { return Stream .of(ListResponse.newBuilder()) .map(r -> r.addAllChannels(channels)) - .map(r -> r.addAllGlobalTypes(globalDispatchers)) - .map(r -> r.addAllPerProjectTypes(perProjectDispatchers)) + .map(r -> r.addAllGlobalTypes(dispatchers.getGlobalDispatchers())) + .map(r -> r.addAllPerProjectTypes(dispatchers.getProjectDispatchers())) .map(addNotifications(dbSession, user)) .map(ListResponse.Builder::build) .collect(toOneElement()); @@ -158,7 +155,7 @@ public class ListAction implements NotificationsWsAction { } private boolean isDispatcherAuthorized(PropertyDto prop, String dispatcher) { - return (prop.getResourceId() != null && perProjectDispatchers.contains(dispatcher)) || globalDispatchers.contains(dispatcher); + return (prop.getResourceId() != null && dispatchers.getProjectDispatchers().contains(dispatcher)) || dispatchers.getGlobalDispatchers().contains(dispatcher); } private Map searchProjects(DbSession dbSession, List properties) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java index 9f9aa9ac64f..6011559edcc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/NotificationWsModule.java @@ -25,6 +25,7 @@ public class NotificationWsModule extends Module { @Override protected void configureModule() { add( + DispatchersImpl.class, // WS NotificationsWs.class, AddAction.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/RemoveAction.java b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/RemoveAction.java index 1a6ea326db8..bc5e6349bdf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notification/ws/RemoveAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/ws/RemoveAction.java @@ -42,33 +42,30 @@ import org.sonar.server.ws.KeyExamples; import static java.util.Optional.empty; import static org.sonar.core.util.Protobuf.setNullable; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; -import static org.sonar.server.ws.WsUtils.checkFound; -import static org.sonar.server.ws.WsUtils.checkRequest; import static org.sonar.server.notification.ws.NotificationsWsParameters.ACTION_REMOVE; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_TYPE; +import static org.sonar.server.ws.WsUtils.checkFound; +import static org.sonar.server.ws.WsUtils.checkRequest; public class RemoveAction implements NotificationsWsAction { private final NotificationCenter notificationCenter; private final NotificationUpdater notificationUpdater; + private final Dispatchers dispatchers; private final DbClient dbClient; private final ComponentFinder componentFinder; private final UserSession userSession; - private final List globalDispatchers; - private final List projectDispatchers; - public RemoveAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) { + public RemoveAction(NotificationCenter notificationCenter, NotificationUpdater notificationUpdater, Dispatchers dispatchers, DbClient dbClient, ComponentFinder componentFinder, + UserSession userSession) { this.notificationCenter = notificationCenter; this.notificationUpdater = notificationUpdater; + this.dispatchers = dispatchers; this.dbClient = dbClient; this.componentFinder = componentFinder; this.userSession = userSession; - this.globalDispatchers = notificationCenter.getDispatcherKeysForProperty(GLOBAL_NOTIFICATION, "true"); - this.projectDispatchers = notificationCenter.getDispatcherKeysForProperty(PER_PROJECT_NOTIFICATION, "true"); } @Override @@ -100,8 +97,8 @@ public class RemoveAction implements NotificationsWsAction { "
  • Global notifications: %s
  • " + "
  • Per project notifications: %s
  • " + "", - globalDispatchers.stream().sorted().collect(Collectors.joining(", ")), - projectDispatchers.stream().sorted().collect(Collectors.joining(", "))) + dispatchers.getGlobalDispatchers().stream().sorted().collect(Collectors.joining(", ")), + dispatchers.getProjectDispatchers().stream().sorted().collect(Collectors.joining(", "))) .setRequired(true) .setExampleValue(MyNewIssuesNotificationDispatcher.KEY); @@ -156,15 +153,15 @@ public class RemoveAction implements NotificationsWsAction { setNullable(request.param(PARAM_LOGIN), remove::setLogin); if (remove.getProject() == null) { - checkRequest(globalDispatchers.contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s", + checkRequest(dispatchers.getGlobalDispatchers().contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s", PARAM_TYPE, remove.getType(), - globalDispatchers); + dispatchers.getGlobalDispatchers()); } else { - checkRequest(projectDispatchers.contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s", + checkRequest(dispatchers.getProjectDispatchers().contains(remove.getType()), "Value of parameter '%s' (%s) must be one of: %s", PARAM_TYPE, remove.getType(), - projectDispatchers); + dispatchers.getProjectDispatchers()); } return remove; diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java index a4be25f44ee..2b2ed031c70 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java @@ -44,6 +44,7 @@ import org.sonarqube.ws.MediaTypes; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.Collections.singletonList; +import static java.util.Objects.requireNonNull; import static org.apache.commons.lang.StringUtils.substring; import static org.apache.commons.lang.StringUtils.substringAfterLast; import static org.apache.commons.lang.StringUtils.substringBeforeLast; @@ -59,19 +60,20 @@ public class WebServiceEngine implements LocalConnector, Startable { private static final Logger LOGGER = Loggers.get(WebServiceEngine.class); - private final WebService.Context context; + private final WebService[] webServices; + + private WebService.Context context; public WebServiceEngine(WebService[] webServices) { - context = new WebService.Context(); - for (WebService webService : webServices) { - webService.define(context); - } + this.webServices = webServices; } @Override public void start() { - // Force execution of constructor to be sure that web services - // are validated and initialized at server startup. + context = new WebService.Context(); + for (WebService webService : webServices) { + webService.define(context); + } } @Override @@ -79,8 +81,12 @@ public class WebServiceEngine implements LocalConnector, Startable { // nothing } + private WebService.Context getContext() { + return requireNonNull(context, "Web services has not yet been initialized"); + } + List controllers() { - return context.controllers(); + return getContext().controllers(); } @Override @@ -117,7 +123,7 @@ public class WebServiceEngine implements LocalConnector, Startable { private WebService.Action getAction(ActionExtractor actionExtractor) { String controllerPath = actionExtractor.getController(); String actionKey = actionExtractor.getAction(); - WebService.Controller controller = context.controller(controllerPath); + WebService.Controller controller = getContext().controller(controllerPath); return controller == null ? null : controller.action(actionKey); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java index 156e6f8efae..6d2b8365c32 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/AddActionTest.java @@ -20,13 +20,11 @@ package org.sonar.server.notification.ws; import javax.annotation.Nullable; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -46,11 +44,14 @@ import org.sonar.server.ws.WsActionTester; import static java.lang.String.format; import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.api.web.UserRole.USER; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.db.component.ComponentTesting.newView; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT; @@ -60,12 +61,11 @@ public class AddActionTest { private static final String NOTIF_MY_NEW_ISSUES = "Dispatcher1"; private static final String NOTIF_NEW_ISSUES = "Dispatcher2"; private static final String NOTIF_NEW_QUALITY_GATE_STATUS = "Dispatcher3"; - private static final String USER_LOGIN = "george.orwell"; @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSession; + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public DbTester db = DbTester.create(); @@ -76,35 +76,19 @@ public class AddActionTest { // default channel, based on class simple name private NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel"); - private UserDto user; - - private NotificationCenter notificationCenter; - private AddAction underTest; - private WsActionTester ws; - - @Before - public void setUp() { - NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - - user = db.users().insertUser(USER_LOGIN); - userSession = UserSessionRule.standalone().logIn(user); - - notificationCenter = new NotificationCenter( - new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3}, - new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}); - underTest = new AddAction(notificationCenter, new NotificationUpdater(dbClient), dbClient, TestComponentFinder.from(db), userSession); - ws = new WsActionTester(underTest); - } + private Dispatchers dispatchers = mock(Dispatchers.class); + + private WsActionTester ws = new WsActionTester(new AddAction(new NotificationCenter( + new NotificationDispatcherMetadata[] {}, + new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}), + new NotificationUpdater(dbClient), dispatchers, dbClient, TestComponentFinder.from(db), userSession)); @Test public void add_to_email_channel_by_default() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + call(NOTIF_MY_NEW_ISSUES, null, null, null); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), null); @@ -112,6 +96,10 @@ public class AddActionTest { @Test public void add_to_a_specific_channel() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + call(NOTIF_NEW_QUALITY_GATE_STATUS, twitterChannel.getKey(), null, null); db.notifications().assertExists(twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, userSession.getUserId(), null); @@ -119,8 +107,12 @@ public class AddActionTest { @Test public void add_notification_on_private_with_USER_permission() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); ComponentDto project = db.components().insertPrivateProject(); - userSession.addProjectPermission(UserRole.USER, project); + userSession.addProjectPermission(USER, project); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null); @@ -129,8 +121,13 @@ public class AddActionTest { @Test public void add_notification_on_public_project() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); ComponentDto project = db.components().insertPublicProject(); userSession.registerComponents(project); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); @@ -138,8 +135,12 @@ public class AddActionTest { @Test public void add_a_global_notification_when_a_project_one_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPrivateProject(); - userSession.addProjectPermission(UserRole.USER, project); + userSession.addProjectPermission(USER, project); call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null); call(NOTIF_MY_NEW_ISSUES, null, null, null); @@ -150,19 +151,26 @@ public class AddActionTest { @Test public void add_a_notification_on_private_project_when_a_global_one_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPrivateProject(); call(NOTIF_MY_NEW_ISSUES, null, null, null); - userSession.addProjectPermission(UserRole.USER, project); + userSession.addProjectPermission(USER, project); call(NOTIF_MY_NEW_ISSUES, null, project.getDbKey(), null); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), project); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, userSession.getUserId(), null); } - @Test public void add_a_notification_on_public_project_when_a_global_one_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPublicProject(); userSession.registerComponents(project); call(NOTIF_MY_NEW_ISSUES, null, null, null); @@ -175,6 +183,10 @@ public class AddActionTest { @Test public void http_no_content() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + TestResponse result = call(NOTIF_MY_NEW_ISSUES, null, null, null); assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT); @@ -182,7 +194,9 @@ public class AddActionTest { @Test public void add_a_notification_to_a_user_as_system_administrator() { - userSession.logIn().setSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); call(NOTIF_MY_NEW_ISSUES, null, null, user.getLogin()); @@ -191,7 +205,9 @@ public class AddActionTest { @Test public void fail_if_login_is_provided_and_unknown() { - userSession.logIn().setSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(NotFoundException.class); expectedException.expectMessage("User 'LOGIN 404' not found"); @@ -201,7 +217,9 @@ public class AddActionTest { @Test public void fail_if_login_provided_and_not_system_administrator() { - userSession.logIn().setNonSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setNonSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(ForbiddenException.class); @@ -210,6 +228,9 @@ public class AddActionTest { @Test public void fail_when_notification_already_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); call(NOTIF_MY_NEW_ISSUES, null, null, null); expectedException.expect(IllegalArgumentException.class); @@ -227,8 +248,12 @@ public class AddActionTest { @Test public void fail_when_unknown_global_dispatcher() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2, Dispatcher3]"); + expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1]"); call("Dispatcher42", null, null, null); } @@ -236,22 +261,28 @@ public class AddActionTest { @Test public void fail_when_unknown_project_dispatcher_on_private_project() { ComponentDto project = db.components().insertPrivateProject(); - userSession.addProjectPermission(UserRole.USER, project); + userSession.addProjectPermission(USER, project); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES)); expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]"); + expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2]"); - call("Dispatcher42", null, project.getDbKey(), null); + call("Dispatcher42", null, project.getKey(), null); } @Test public void fail_when_unknown_project_dispatcher_on_public_project() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); ComponentDto project = db.components().insertPublicProject(); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES)); expectedException.expect(BadRequestException.class); - expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher3]"); + expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2]"); - call("Dispatcher42", null, project.getDbKey(), null); + call("Dispatcher42", null, project.getKey(), null); } @Test @@ -263,6 +294,11 @@ public class AddActionTest { @Test public void fail_when_project_is_unknown() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(NotFoundException.class); call(NOTIF_MY_NEW_ISSUES, null, "Project-42", null); @@ -270,7 +306,11 @@ public class AddActionTest { @Test public void fail_when_component_is_not_a_project() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); db.components().insertViewAndSnapshot(newView(db.organizations().insert()).setDbKey("VIEW_1")); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(BadRequestException.class); expectedException.expectMessage("Component 'VIEW_1' must be a project"); @@ -281,6 +321,7 @@ public class AddActionTest { @Test public void fail_when_not_authenticated() { userSession.anonymous(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(UnauthorizedException.class); @@ -289,6 +330,9 @@ public class AddActionTest { @Test public void fail_when_using_branch_db_key() throws Exception { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertMainBranch(); ComponentDto branch = db.components().insertProjectBranch(project); @@ -302,6 +346,8 @@ public class AddActionTest { public void fail_when_user_does_not_have_USER_permission_on_private_project() { ComponentDto project = db.components().insertPrivateProject(); userSession.logIn().setNonRoot().setNonSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(ForbiddenException.class); diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/DispatchersImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/DispatchersImplTest.java new file mode 100644 index 00000000000..1ea655deca5 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/DispatchersImplTest.java @@ -0,0 +1,93 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.notification.ws; + +import org.junit.Test; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.server.event.NewAlerts; +import org.sonar.server.issue.notification.DoNotFixNotificationDispatcher; +import org.sonar.server.issue.notification.MyNewIssuesNotificationDispatcher; +import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher; +import org.sonar.server.notification.NotificationCenter; +import org.sonar.server.notification.NotificationDispatcherMetadata; + +import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; +import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; + +public class DispatchersImplTest { + + private NotificationCenter notificationCenter = new NotificationCenter( + new NotificationDispatcherMetadata[] { + NotificationDispatcherMetadata.create(MyNewIssuesNotificationDispatcher.KEY) + .setProperty(GLOBAL_NOTIFICATION, "true") + .setProperty(PER_PROJECT_NOTIFICATION, "true"), + NotificationDispatcherMetadata.create(NewIssuesNotificationDispatcher.KEY) + .setProperty(GLOBAL_NOTIFICATION, "true"), + NotificationDispatcherMetadata.create(NewAlerts.KEY) + .setProperty(GLOBAL_NOTIFICATION, "true") + .setProperty(PER_PROJECT_NOTIFICATION, "true"), + NotificationDispatcherMetadata.create(DoNotFixNotificationDispatcher.KEY) + .setProperty(GLOBAL_NOTIFICATION, "true") + .setProperty(PER_PROJECT_NOTIFICATION, "true") + }, + new NotificationChannel[] {}); + + private final MapSettings settings = new MapSettings(); + + private DispatchersImpl underTest = new DispatchersImpl(notificationCenter, settings.asConfig()); + + @Test + public void get_sorted_global_dispatchers() { + underTest.start(); + + assertThat(underTest.getGlobalDispatchers()).containsExactly( + NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY, NewIssuesNotificationDispatcher.KEY, MyNewIssuesNotificationDispatcher.KEY); + } + + @Test + public void get_global_dispatchers_on_sonar_cloud() { + settings.setProperty("sonar.sonarcloud.enabled", "true"); + + underTest.start(); + + assertThat(underTest.getGlobalDispatchers()).containsOnly(MyNewIssuesNotificationDispatcher.KEY); + } + + @Test + public void get_sorted_project_dispatchers() { + underTest.start(); + + assertThat(underTest.getProjectDispatchers()).containsExactly( + NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY, MyNewIssuesNotificationDispatcher.KEY); + } + + @Test + public void get_project_dispatchers_on_sonar_cloud() { + settings.setProperty("sonar.sonarcloud.enabled", "true"); + + underTest.start(); + + assertThat(underTest.getProjectDispatchers()).containsOnly( + MyNewIssuesNotificationDispatcher.KEY, NewAlerts.KEY, DoNotFixNotificationDispatcher.KEY); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/ListActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/ListActionTest.java index 00affd980b1..f909bc781e7 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/ListActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/ListActionTest.java @@ -19,20 +19,16 @@ */ package org.sonar.server.notification.ws; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.notifications.NotificationChannel; import org.sonar.api.server.ws.WebService; -import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.UserPermissionDto; import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; @@ -45,10 +41,13 @@ import org.sonar.server.ws.WsActionTester; import org.sonarqube.ws.Notifications.ListResponse; import org.sonarqube.ws.Notifications.Notification; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.api.web.UserRole.USER; import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; import static org.sonar.test.JsonAssert.assertJson; @@ -60,7 +59,7 @@ public class ListActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSession; + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public DbTester db = DbTester.create(); @@ -69,36 +68,20 @@ public class ListActionTest { private NotificationChannel emailChannel = new FakeNotificationChannel("EmailChannel"); private NotificationChannel twitterChannel = new FakeNotificationChannel("TwitterChannel"); - private UserDto user; - - private NotificationUpdater notificationUpdater; - - private WsActionTester ws; - - @Before - public void setUp() { - NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - - user = db.users().insertUser(); - userSession = UserSessionRule.standalone().logIn(user); - - NotificationCenter notificationCenter = new NotificationCenter( - new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3}, - new NotificationChannel[] {emailChannel, twitterChannel}); - notificationUpdater = new NotificationUpdater(dbClient); - ListAction underTest = new ListAction(notificationCenter, dbClient, userSession); - ws = new WsActionTester(underTest); - } + + private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient); + private Dispatchers dispatchers = mock(Dispatchers.class); + + private WsActionTester ws = new WsActionTester(new ListAction(new NotificationCenter( + new NotificationDispatcherMetadata[] {}, + new NotificationChannel[] {emailChannel, twitterChannel}), + dbClient, userSession, dispatchers)); @Test public void channels() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + ListResponse result = call(); assertThat(result.getChannelsList()).containsExactly(emailChannel.getKey(), twitterChannel.getKey()); @@ -106,6 +89,10 @@ public class ListActionTest { @Test public void overall_dispatchers() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + ListResponse result = call(); assertThat(result.getGlobalTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS); @@ -113,6 +100,10 @@ public class ListActionTest { @Test public void per_project_dispatchers() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + ListResponse result = call(); assertThat(result.getPerProjectTypesList()).containsExactly(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS); @@ -120,7 +111,12 @@ public class ListActionTest { @Test public void filter_unauthorized_projects() { - ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("K1")); + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + ComponentDto project = db.components().insertPrivateProject(); + db.users().insertProjectPermissionOnUser(user, USER, project); ComponentDto anotherProject = db.components().insertPrivateProject(); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, anotherProject); @@ -128,11 +124,14 @@ public class ListActionTest { ListResponse result = call(); - assertThat(result.getNotificationsList()).extracting(Notification::getProject).containsOnly("K1"); + assertThat(result.getNotificationsList()).extracting(Notification::getProject).containsOnly(project.getKey()); } @Test public void filter_channels() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, "Unknown Channel", NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -144,6 +143,9 @@ public class ListActionTest { @Test public void filter_overall_dispatchers() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), "Unknown Notification", user, null); dbSession.commit(); @@ -155,7 +157,11 @@ public class ListActionTest { @Test public void filter_per_project_dispatchers() { - ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(db.organizations().insert()).setDbKey("K1")); + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + ComponentDto project = db.components().insertPrivateProject(); + db.users().insertProjectPermissionOnUser(user, USER, project); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project); notificationUpdater.add(dbSession, emailChannel.getKey(), "Unknown Notification", user, project); dbSession.commit(); @@ -169,8 +175,13 @@ public class ListActionTest { @Test public void order_with_global_then_by_channel_and_dispatcher() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); OrganizationDto organization = db.organizations().insert(); - ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(organization).setDbKey("K1")); + ComponentDto project = db.components().insertPrivateProject(organization); + db.users().insertProjectPermissionOnUser(user, USER, project); notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null); @@ -187,15 +198,16 @@ public class ListActionTest { tuple(emailChannel.getKey(), "", NOTIF_MY_NEW_ISSUES, ""), tuple(emailChannel.getKey(), "", NOTIF_NEW_ISSUES, ""), tuple(twitterChannel.getKey(), "", NOTIF_MY_NEW_ISSUES, ""), - tuple(emailChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, "K1"), - tuple(emailChannel.getKey(), organization.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, "K1"), - tuple(twitterChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, "K1")); + tuple(emailChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey()), + tuple(emailChannel.getKey(), organization.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, project.getKey()), + tuple(twitterChannel.getKey(), organization.getKey(), NOTIF_MY_NEW_ISSUES, project.getKey())); } @Test public void list_user_notifications_as_system_admin() { - userSession.logIn().setSystemAdministrator(); - + UserDto user = db.users().insertUser(); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + userSession.logIn(user).setSystemAdministrator(); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null); dbSession.commit(); @@ -209,7 +221,9 @@ public class ListActionTest { @Test public void fail_if_login_and_not_system_admin() { - userSession.logIn().setNonSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setNonSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -230,8 +244,13 @@ public class ListActionTest { @Test public void json_example() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); OrganizationDto organization = db.organizations().insertForKey("my-org-1"); - ComponentDto project = addComponent(ComponentTesting.newPrivateProjectDto(organization).setDbKey(KEY_PROJECT_EXAMPLE_001).setName("My Project")); + ComponentDto project = db.components().insertPrivateProject(organization, p -> p.setDbKey(KEY_PROJECT_EXAMPLE_001).setName("My Project")); + db.users().insertProjectPermissionOnUser(user, USER, project); notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); notificationUpdater.add(dbSession, emailChannel.getKey(), NOTIF_NEW_ISSUES, user, null); @@ -279,14 +298,6 @@ public class ListActionTest { return ws.newRequest().setParam("login", login).executeProtobuf(ListResponse.class); } - private ComponentDto addComponent(ComponentDto component) { - db.components().insertComponent(component); - dbClient.userPermissionDao().insert(dbSession, new UserPermissionDto(component.getOrganizationUuid(), UserRole.USER, user.getId(), component.getId())); - db.commit(); - - return component; - } - private static class FakeNotificationChannel extends NotificationChannel { private final String key; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java index 6164a893750..792269526c6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/NotificationWsModuleTest.java @@ -29,6 +29,6 @@ public class NotificationWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new NotificationWsModule().configure(container); - assertThat(container.size()).isEqualTo(4 + 2); + assertThat(container.size()).isEqualTo(5 + 2); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/RemoveActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/RemoveActionTest.java index a21bfa28eb3..f94dce62d3d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notification/ws/RemoveActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/ws/RemoveActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.notification.ws; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -46,11 +45,13 @@ import org.sonar.server.ws.WsActionTester; import static java.lang.String.format; import static java.net.HttpURLConnection.HTTP_NO_CONTENT; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.db.component.ComponentTesting.newView; -import static org.sonar.server.notification.NotificationDispatcherMetadata.GLOBAL_NOTIFICATION; -import static org.sonar.server.notification.NotificationDispatcherMetadata.PER_PROJECT_NOTIFICATION; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_CHANNEL; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_LOGIN; import static org.sonar.server.notification.ws.NotificationsWsParameters.PARAM_PROJECT; @@ -63,7 +64,7 @@ public class RemoveActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSession; + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule public DbTester db = DbTester.create(); private DbClient dbClient = db.getDbClient(); @@ -74,39 +75,20 @@ public class RemoveActionTest { // default channel, based on class simple name private NotificationChannel defaultChannel = new FakeNotificationChannel("EmailNotificationChannel"); - private NotificationCenter notificationCenter; - private NotificationUpdater notificationUpdater; - private RemoveAction underTest; + private NotificationUpdater notificationUpdater = new NotificationUpdater(dbClient); + private Dispatchers dispatchers = mock(Dispatchers.class); - private WsActionTester ws; private RemoveRequest request = new RemoveRequest().setType(NOTIF_MY_NEW_ISSUES); - private UserDto user; - - @Before - public void setUp() { - user = db.users().insertUser(); - userSession = UserSessionRule.standalone().logIn(user); - - NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create(NOTIF_MY_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create(NOTIF_NEW_ISSUES) - .setProperty(GLOBAL_NOTIFICATION, "true"); - NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create(NOTIF_NEW_QUALITY_GATE_STATUS) - .setProperty(GLOBAL_NOTIFICATION, "true") - .setProperty(PER_PROJECT_NOTIFICATION, "true"); - - notificationCenter = new NotificationCenter( - new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3}, - new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}); - notificationUpdater = new NotificationUpdater(dbClient); - underTest = new RemoveAction(notificationCenter, notificationUpdater, dbClient, TestComponentFinder.from(db), userSession); - ws = new WsActionTester(underTest); - } + private WsActionTester ws = new WsActionTester(new RemoveAction(new NotificationCenter( + new NotificationDispatcherMetadata[] {}, + new NotificationChannel[] {emailChannel, twitterChannel, defaultChannel}), notificationUpdater, dispatchers, dbClient, TestComponentFinder.from(db), userSession)); @Test public void remove_to_email_channel_by_default() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -117,6 +99,9 @@ public class RemoveActionTest { @Test public void remove_from_a_specific_channel() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_NEW_QUALITY_GATE_STATUS)); notificationUpdater.add(dbSession, twitterChannel.getKey(), NOTIF_NEW_QUALITY_GATE_STATUS, user, null); dbSession.commit(); @@ -127,6 +112,10 @@ public class RemoveActionTest { @Test public void remove_a_project_notification() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPrivateProject(); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project); dbSession.commit(); @@ -138,6 +127,10 @@ public class RemoveActionTest { @Test public void fail_when_remove_a_global_notification_when_a_project_one_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPrivateProject(); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, project); dbSession.commit(); @@ -150,6 +143,10 @@ public class RemoveActionTest { @Test public void fail_when_remove_a_project_notification_when_a_global_one_exists() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertPrivateProject(); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -162,6 +159,10 @@ public class RemoveActionTest { @Test public void http_no_content() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -172,6 +173,9 @@ public class RemoveActionTest { @Test public void remove_a_notification_from_a_user_as_system_administrator() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); db.notifications().assertExists(defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user.getId(), null); userSession.logIn().setSystemAdministrator(); @@ -184,7 +188,9 @@ public class RemoveActionTest { @Test public void fail_if_login_is_provided_and_unknown() { - userSession.logIn().setSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(NotFoundException.class); expectedException.expectMessage("User 'LOGIN 404' not found"); @@ -194,7 +200,9 @@ public class RemoveActionTest { @Test public void fail_if_login_provided_and_not_system_administrator() { - userSession.logIn().setNonSystemAdministrator(); + UserDto user = db.users().insertUser(); + userSession.logIn(user).setNonSystemAdministrator(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); notificationUpdater.add(dbSession, defaultChannel.getKey(), NOTIF_MY_NEW_ISSUES, user, null); dbSession.commit(); @@ -205,6 +213,10 @@ public class RemoveActionTest { @Test public void fail_when_notification_does_not_exist() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Notification doesn't exist"); @@ -213,6 +225,10 @@ public class RemoveActionTest { @Test public void fail_when_unknown_channel() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(IllegalArgumentException.class); call(request.setChannel("Channel42")); @@ -220,6 +236,10 @@ public class RemoveActionTest { @Test public void fail_when_unknown_global_dispatcher() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); + expectedException.expect(BadRequestException.class); expectedException.expectMessage("Value of parameter 'type' (Dispatcher42) must be one of: [Dispatcher1, Dispatcher2, Dispatcher3]"); @@ -228,6 +248,10 @@ public class RemoveActionTest { @Test public void fail_when_unknown_project_dispatcher() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(asList(NOTIF_MY_NEW_ISSUES, NOTIF_NEW_QUALITY_GATE_STATUS)); ComponentDto project = db.components().insertPrivateProject(); expectedException.expect(BadRequestException.class); @@ -237,14 +261,24 @@ public class RemoveActionTest { } @Test - public void fail_when_no_dispatcher() { + public void fail_when_no_type_parameter() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("The 'type' parameter is missing"); ws.newRequest().execute(); } @Test public void fail_when_project_is_unknown() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + expectedException.expect(NotFoundException.class); call(request.setProject("Project-42")); @@ -252,6 +286,10 @@ public class RemoveActionTest { @Test public void fail_when_component_is_not_a_project() { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); db.components().insertViewAndSnapshot(newView(db.organizations().insert()).setDbKey("VIEW_1")); expectedException.expect(BadRequestException.class); @@ -263,6 +301,7 @@ public class RemoveActionTest { @Test public void fail_when_not_authenticated() { userSession.anonymous(); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); expectedException.expect(UnauthorizedException.class); @@ -271,6 +310,10 @@ public class RemoveActionTest { @Test public void fail_when_using_branch_db_key() throws Exception { + UserDto user = db.users().insertUser(); + userSession.logIn(user); + when(dispatchers.getGlobalDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); + when(dispatchers.getProjectDispatchers()).thenReturn(singletonList(NOTIF_MY_NEW_ISSUES)); ComponentDto project = db.components().insertMainBranch(); ComponentDto branch = db.components().insertProjectBranch(project); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SearchActionTest.java index d4310413a0b..72983d3761f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SearchActionTest.java @@ -24,7 +24,6 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.server.ws.WebService; import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; @@ -65,7 +64,6 @@ public class SearchActionTest { public DbTester db = DbTester.create(); private DbClient dbClient = db.getDbClient(); - private DbSession dbSession = db.getSession(); private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db); private SearchAction underTest = new SearchAction(dbClient, userSession, new QualityGateFinder(dbClient), diff --git a/server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java index 5c1490a1063..90367828948 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java @@ -56,8 +56,10 @@ public class WebServiceEngineTest { @Test public void load_ws_definitions_at_startup() { WebServiceEngine underTest = new WebServiceEngine(new WebService[] { - newWs("api/foo/index", a -> {}), - newWs("api/bar/index", a -> {}) + newWs("api/foo/index", a -> { + }), + newWs("api/bar/index", a -> { + }) }); underTest.start(); try { @@ -204,8 +206,7 @@ public class WebServiceEngineTest { public void fail_if_reading_an_undefined_parameter() { Request request = new TestRequest().setPath("api/foo").setParam("unknown", "Unknown"); - DumbResponse response = run(request, newWs("api/foo", a -> - a.setHandler((req, resp) -> request.param("unknown")))); + DumbResponse response = run(request, newWs("api/foo", a -> a.setHandler((req, resp) -> request.param("unknown")))); assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"BUG - parameter 'unknown' is undefined for action 'foo'\"}]}"); assertThat(response.stream().status()).isEqualTo(400); @@ -404,6 +405,18 @@ public class WebServiceEngineTest { assertThat(logTester.logs(LoggerLevel.ERROR)).contains("Fail to process request api/foo"); } + @Test + public void fail_when_start_in_not_called() { + Request request = new TestRequest().setPath("/api/ping"); + DumbResponse response = new DumbResponse(); + WebServiceEngine underTest = new WebServiceEngine(new WebService[] {newPingWs(a -> { + })}); + + underTest.execute(request, response); + + assertThat(logTester.logs(LoggerLevel.ERROR)).contains("Fail to process request /api/ping"); + } + private static WebService newWs(String path, Consumer consumer) { return context -> { WebService.NewController controller = context.createController(substringBeforeLast(path, "/")); @@ -430,7 +443,7 @@ public class WebServiceEngineTest { private static DumbResponse run(Request request, WebService... webServices) { DumbResponse response = new DumbResponse(); - return (DumbResponse)run(request, response, webServices); + return (DumbResponse) run(request, response, webServices); } private static Response run(Request request, Response response, WebService... webServices) { diff --git a/tests/src/test/java/org/sonarqube/tests/Category1Suite.java b/tests/src/test/java/org/sonarqube/tests/Category1Suite.java index b29280ba12f..89368b1488a 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category1Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category1Suite.java @@ -28,7 +28,6 @@ import org.sonarqube.tests.settings.DeprecatedPropertiesWsTest; import org.sonarqube.tests.settings.EmailsTest; import org.sonarqube.tests.settings.PropertySetsTest; import org.sonarqube.tests.settings.SettingsTest; -import org.sonarqube.tests.user.UsersPageTest; import static util.ItUtils.pluginArtifact; import static util.ItUtils.xooPlugin; @@ -40,7 +39,6 @@ import static util.ItUtils.xooPlugin; @Deprecated @RunWith(Suite.class) @Suite.SuiteClasses({ - UsersPageTest.class, BackgroundTasksTest.class, DeprecatedPropertiesWsTest.class, EmailsTest.class, @@ -61,7 +59,6 @@ public class Category1Suite { // Used in SettingsTest.should_get_settings_default_value .addPlugin(pluginArtifact("server-plugin")) - // Used in I18nTest .addPlugin(pluginArtifact("l10n-fr-pack")) diff --git a/tests/src/test/java/org/sonarqube/tests/Category4Suite.java b/tests/src/test/java/org/sonarqube/tests/Category4Suite.java index 3745186d27a..332ef87afe1 100644 --- a/tests/src/test/java/org/sonarqube/tests/Category4Suite.java +++ b/tests/src/test/java/org/sonarqube/tests/Category4Suite.java @@ -36,13 +36,6 @@ import org.sonarqube.tests.serverSystem.ServerSystemTest; import org.sonarqube.tests.serverSystem.SystemInfoTest; import org.sonarqube.tests.ui.UiExtensionsTest; import org.sonarqube.tests.ui.UiTest; -import org.sonarqube.tests.user.BaseIdentityProviderTest; -import org.sonarqube.tests.user.FavoritesWsTest; -import org.sonarqube.tests.user.ForceAuthenticationTest; -import org.sonarqube.tests.user.LocalAuthenticationTest; -import org.sonarqube.tests.user.MyAccountPageTest; -import org.sonarqube.tests.user.OAuth2IdentityProviderTest; -import org.sonarqube.tests.user.RootUserInStandaloneModeTest; import org.sonarqube.tests.ws.WsLocalCallTest; import org.sonarqube.tests.ws.WsTest; @@ -56,20 +49,10 @@ import static util.ItUtils.xooPlugin; @Deprecated @RunWith(Suite.class) @Suite.SuiteClasses({ - // organization - RootUserInStandaloneModeTest.class, // server system ServerSystemTest.class, SystemInfoTest.class, PingTest.class, - // user - MyAccountPageTest.class, - FavoritesWsTest.class, - // authentication - ForceAuthenticationTest.class, - LocalAuthenticationTest.class, - BaseIdentityProviderTest.class, - OAuth2IdentityProviderTest.class, // analysis exclusion FileExclusionsTest.class, IssueExclusionsTest.class, @@ -95,12 +78,6 @@ public class Category4Suite { public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv() .addPlugin(xooPlugin()) - // Used in BaseIdentityProviderTest - .addPlugin(pluginArtifact("base-auth-plugin")) - - // Used in OAuth2IdentityProviderTest - .addPlugin(pluginArtifact("oauth2-auth-plugin")) - // Used in UiExtensionsTest .addPlugin(pluginArtifact("ui-extensions-plugin")) @@ -113,7 +90,5 @@ public class Category4Suite { // reduce memory for Elasticsearch to 128M .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m") - .setServerProperty("sonar.web.javaAdditionalOpts", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8001") - .build(); } diff --git a/tests/src/test/java/org/sonarqube/tests/user/BaseIdentityProviderTest.java b/tests/src/test/java/org/sonarqube/tests/user/BaseIdentityProviderTest.java index e445488536d..9ecf5aa4e3a 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/BaseIdentityProviderTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/BaseIdentityProviderTest.java @@ -31,7 +31,6 @@ import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.RuleChain; import org.sonarqube.qa.util.pageobjects.Navigation; -import org.sonarqube.tests.Category4Suite; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.users.CreateRequest; @@ -51,7 +50,7 @@ import static util.selenium.Selenese.runSelenese; public class BaseIdentityProviderTest { @ClassRule - public static Orchestrator ORCHESTRATOR = Category4Suite.ORCHESTRATOR; + public static Orchestrator ORCHESTRATOR = UserSuite.ORCHESTRATOR; private static UserRule userRule = UserRule.from(ORCHESTRATOR); diff --git a/tests/src/test/java/org/sonarqube/tests/user/FavoritesWsTest.java b/tests/src/test/java/org/sonarqube/tests/user/FavoritesWsTest.java index 55b09ea4b64..0dac746ecd9 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/FavoritesWsTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/FavoritesWsTest.java @@ -25,7 +25,6 @@ import java.util.List; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; -import org.sonarqube.tests.Category4Suite; import org.sonarqube.ws.Favorites.Favorite; import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.favorites.AddRequest; @@ -42,7 +41,8 @@ import static util.ItUtils.projectDir; public class FavoritesWsTest { @ClassRule - public static final Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR; + private static WsClient adminClient; @Before diff --git a/tests/src/test/java/org/sonarqube/tests/user/ForceAuthenticationTest.java b/tests/src/test/java/org/sonarqube/tests/user/ForceAuthenticationTest.java index d3a4cb71cb7..4bf5885476c 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/ForceAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/ForceAuthenticationTest.java @@ -20,13 +20,13 @@ package org.sonarqube.tests.user; import com.sonar.orchestrator.Orchestrator; -import org.sonarqube.tests.Category4Suite; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.pageobjects.Navigation; import org.sonarqube.ws.Users.CreateWsResponse.User; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.PostRequest; @@ -34,7 +34,6 @@ import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.WsConnector; import org.sonarqube.ws.client.WsRequest; import org.sonarqube.ws.client.WsResponse; -import org.sonarqube.qa.util.pageobjects.Navigation; import static org.assertj.core.api.Assertions.assertThat; import static org.sonarqube.ws.client.WsRequest.Method.GET; @@ -45,7 +44,7 @@ import static util.ItUtils.setServerProperty; public class ForceAuthenticationTest { @ClassRule - public static final Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR; @Rule public Tester tester = new Tester(orchestrator).disableOrganizations(); diff --git a/tests/src/test/java/org/sonarqube/tests/user/LocalAuthenticationTest.java b/tests/src/test/java/org/sonarqube/tests/user/LocalAuthenticationTest.java index fc3707f322e..3f56905e7b2 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/LocalAuthenticationTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/LocalAuthenticationTest.java @@ -29,7 +29,6 @@ import org.junit.Test; import org.sonarqube.qa.util.Tester; import org.sonarqube.qa.util.pageobjects.LoginPage; import org.sonarqube.qa.util.pageobjects.Navigation; -import org.sonarqube.tests.Category4Suite; import org.sonarqube.ws.UserTokens; import org.sonarqube.ws.Users; import org.sonarqube.ws.Users.CreateWsResponse.User; @@ -56,7 +55,7 @@ import static util.ItUtils.setServerProperty; public class LocalAuthenticationTest { @ClassRule - public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR; @Rule public Tester tester = new Tester(orchestrator).disableOrganizations(); diff --git a/tests/src/test/java/org/sonarqube/tests/user/MyAccountPageTest.java b/tests/src/test/java/org/sonarqube/tests/user/MyAccountPageTest.java index 226082b75b1..ec7ddee7474 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/MyAccountPageTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/MyAccountPageTest.java @@ -25,9 +25,8 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.sonarqube.qa.util.pageobjects.Navigation; -import org.sonarqube.tests.Category4Suite; import org.sonarqube.qa.util.Tester; +import org.sonarqube.qa.util.pageobjects.Navigation; import org.sonarqube.ws.Users.CreateWsResponse.User; import org.sonarqube.ws.client.PostRequest; @@ -40,7 +39,7 @@ import static util.selenium.Selenese.runSelenese; public class MyAccountPageTest { @ClassRule - public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR; @Rule public Tester tester = new Tester(orchestrator).disableOrganizations(); diff --git a/tests/src/test/java/org/sonarqube/tests/user/NotificationsWsTest.java b/tests/src/test/java/org/sonarqube/tests/user/NotificationsWsTest.java new file mode 100644 index 00000000000..2dc9de4022c --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/user/NotificationsWsTest.java @@ -0,0 +1,137 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.tests.user; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.Notifications; +import org.sonarqube.ws.Notifications.Notification; +import org.sonarqube.ws.Projects; +import org.sonarqube.ws.Users; +import org.sonarqube.ws.client.notifications.AddRequest; +import org.sonarqube.ws.client.notifications.ListRequest; +import org.sonarqube.ws.client.notifications.RemoveRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +public class NotificationsWsTest { + + @ClassRule + public static final Orchestrator orchestrator = UserSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator).disableOrganizations(); + + @Test + public void list_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + + Notifications.ListResponse list = tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()); + + assertThat(list.getNotificationsList()).isEmpty(); + assertThat(list.getChannelsList()).containsExactlyInAnyOrder("EmailNotificationChannel"); + assertThat(list.getGlobalTypesList()).containsExactlyInAnyOrder( + "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues"); + assertThat(list.getPerProjectTypesList()).containsExactlyInAnyOrder( + "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues"); + } + + @Test + public void add_global_and_project_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()) + .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName) + .containsExactlyInAnyOrder( + tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""), + tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName())); + } + + @Test + public void remove_global_and_project_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + // These 2 notifications will be removed + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + // These 2 notifications will not be removed + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewAlerts")); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("SQ-MyNewIssues").setProject(project.getKey())); + + tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()) + .extracting(Notification::getType, Notification::getProject) + .containsExactlyInAnyOrder( + tuple("NewAlerts", ""), + tuple("SQ-MyNewIssues", project.getKey())); + } + + @Test + public void add_global_and_project_notifications_on_another_user_as_a_system_administrator() { + Users.CreateWsResponse.User admin = tester.users().generateAdministratorOnDefaultOrganization(); + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(admin.getLogin()).wsClient().notifications().list(new ListRequest().setLogin(user.getLogin())).getNotificationsList()) + .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName) + .containsExactlyInAnyOrder( + tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""), + tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName())); + } + + @Test + public void remove_global_and_project_notifications_on_another_user_as_a_system_administrator() { + Users.CreateWsResponse.User admin = tester.users().generateAdministratorOnDefaultOrganization(); + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + // These 2 notifications will be removed + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + // These 2 notifications will not be removed + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewAlerts")); + tester.as(admin.getLogin()).wsClient().notifications().add(new AddRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("SQ-MyNewIssues").setProject(project.getKey())); + + tester.as(admin.getLogin()).wsClient().notifications().remove(new RemoveRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(admin.getLogin()).wsClient().notifications().remove(new RemoveRequest().setLogin(user.getLogin()).setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(admin.getLogin()).wsClient().notifications().list(new ListRequest().setLogin(user.getLogin())).getNotificationsList()) + .extracting(Notification::getType, Notification::getProject) + .containsExactlyInAnyOrder( + tuple("NewAlerts", ""), + tuple("SQ-MyNewIssues", project.getKey())); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/user/OAuth2IdentityProviderTest.java b/tests/src/test/java/org/sonarqube/tests/user/OAuth2IdentityProviderTest.java index 9ad8f1a79cc..103b634ccd7 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/OAuth2IdentityProviderTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/OAuth2IdentityProviderTest.java @@ -33,7 +33,6 @@ import org.junit.Rule; import org.junit.Test; import org.sonarqube.qa.util.Tester; import org.sonarqube.qa.util.pageobjects.Navigation; -import org.sonarqube.tests.Category4Suite; import org.sonarqube.ws.Users.SearchWsResponse.User; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.permissions.AddUserRequest; @@ -50,7 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class OAuth2IdentityProviderTest { @ClassRule - public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR; private static String FAKE_PROVIDER_KEY = "fake-oauth2-id-provider"; diff --git a/tests/src/test/java/org/sonarqube/tests/user/RootUserInStandaloneModeTest.java b/tests/src/test/java/org/sonarqube/tests/user/RootUserInStandaloneModeTest.java index fcb1d62c868..bb5fe85f6b3 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/RootUserInStandaloneModeTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/RootUserInStandaloneModeTest.java @@ -20,7 +20,6 @@ package org.sonarqube.tests.user; import com.sonar.orchestrator.Orchestrator; -import org.sonarqube.tests.Category4Suite; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -31,7 +30,7 @@ import static util.ItUtils.expectForbiddenError; public class RootUserInStandaloneModeTest { @ClassRule - public static Orchestrator orchestrator = Category4Suite.ORCHESTRATOR; + public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR; @Rule public Tester tester = new Tester(orchestrator).disableOrganizations(); diff --git a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudNotificationsWsTest.java b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudNotificationsWsTest.java new file mode 100644 index 00000000000..f6426b48981 --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudNotificationsWsTest.java @@ -0,0 +1,110 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.tests.user; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.qa.util.Tester; +import org.sonarqube.ws.Notifications; +import org.sonarqube.ws.Notifications.Notification; +import org.sonarqube.ws.Projects; +import org.sonarqube.ws.Users; +import org.sonarqube.ws.client.notifications.AddRequest; +import org.sonarqube.ws.client.notifications.ListRequest; +import org.sonarqube.ws.client.notifications.RemoveRequest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static util.ItUtils.expectHttpError; + +public class SonarCloudNotificationsWsTest { + + @ClassRule + public static final Orchestrator orchestrator = SonarCloudUserSuite.ORCHESTRATOR; + + @Rule + public Tester tester = new Tester(orchestrator); + + @Test + public void list_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + + Notifications.ListResponse list = tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()); + + assertThat(list.getNotificationsList()).isEmpty(); + assertThat(list.getChannelsList()).containsExactlyInAnyOrder("EmailNotificationChannel"); + assertThat(list.getGlobalTypesList()) + .containsExactlyInAnyOrder( + "CeReportTaskFailure", "ChangesOnMyIssue", "SQ-MyNewIssues") + .doesNotContain("NewAlerts", "NewFalsePositiveIssue", "NewIssues"); + assertThat(list.getPerProjectTypesList()).containsExactlyInAnyOrder( + "CeReportTaskFailure", "ChangesOnMyIssue", "NewAlerts", "NewFalsePositiveIssue", "NewIssues", "SQ-MyNewIssues"); + } + + @Test + public void add_global_and_project_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()) + .extracting(Notification::getChannel, Notification::getType, Notification::getProject, Notification::getProjectName) + .containsExactlyInAnyOrder( + tuple("EmailNotificationChannel", "ChangesOnMyIssue", "", ""), + tuple("EmailNotificationChannel", "NewIssues", project.getKey(), project.getName())); + } + + @Test + public void remove_global_and_project_notifications() { + Users.CreateWsResponse.User user = tester.users().generate(); + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + Projects.CreateWsResponse.Project project = tester.projects().provision(); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("ChangesOnMyIssue")); + tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues").setProject(project.getKey())); + + assertThat(tester.as(user.getLogin()).wsClient().notifications().list(new ListRequest()).getNotificationsList()).isEmpty(); + } + + @Test + public void fail_to_add_global_new_issues_notification() { + Users.CreateWsResponse.User user = tester.users().generate(); + + expectHttpError(400, + "Value of parameter 'type' (NewIssues) must be one of: [CeReportTaskFailure, ChangesOnMyIssue, SQ-MyNewIssues]", + () -> tester.as(user.getLogin()).wsClient().notifications().add(new AddRequest().setChannel("EmailNotificationChannel").setType("NewIssues"))); + } + + @Test + public void fail_to_remove_global_new_issues_notification() { + Users.CreateWsResponse.User user = tester.users().generate(); + + expectHttpError(400, + "Value of parameter 'type' (NewIssues) must be one of: [CeReportTaskFailure, ChangesOnMyIssue, SQ-MyNewIssues]", + () -> tester.as(user.getLogin()).wsClient().notifications().remove(new RemoveRequest().setChannel("EmailNotificationChannel").setType("NewIssues"))); + } +} diff --git a/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUserSuite.java b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUserSuite.java new file mode 100644 index 00000000000..b14ad6da627 --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/user/SonarCloudUserSuite.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonarqube.tests.user; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import static util.ItUtils.xooPlugin; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + SonarCloudNotificationsWsTest.class +}) +public class SonarCloudUserSuite { + + @ClassRule + public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv() + .addPlugin(xooPlugin()) + + .setServerProperty("sonar.sonarcloud.enabled", "true") + + // reduce memory for Elasticsearch + .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m") + + .build(); + +} diff --git a/tests/src/test/java/org/sonarqube/tests/user/UserSuite.java b/tests/src/test/java/org/sonarqube/tests/user/UserSuite.java new file mode 100644 index 00000000000..d6b4ddb36ed --- /dev/null +++ b/tests/src/test/java/org/sonarqube/tests/user/UserSuite.java @@ -0,0 +1,60 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonarqube.tests.user; + +import com.sonar.orchestrator.Orchestrator; +import org.junit.ClassRule; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import static util.ItUtils.pluginArtifact; +import static util.ItUtils.xooPlugin; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + BaseIdentityProviderTest.class, + FavoritesWsTest.class, + ForceAuthenticationTest.class, + LocalAuthenticationTest.class, + MyAccountPageTest.class, + NotificationsWsTest.class, + OAuth2IdentityProviderTest.class, + RootUserInStandaloneModeTest.class, + UsersPageTest.class +}) +public class UserSuite { + + @ClassRule + public static final Orchestrator ORCHESTRATOR = Orchestrator.builderEnv() + .addPlugin(xooPlugin()) + + // Used in BaseIdentityProviderTest + .addPlugin(pluginArtifact("base-auth-plugin")) + + // Used in OAuth2IdentityProviderTest + .addPlugin(pluginArtifact("oauth2-auth-plugin")) + + // reduce memory for Elasticsearch + .setServerProperty("sonar.search.javaOpts", "-Xms128m -Xmx128m") + + .build(); + +} diff --git a/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java b/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java index a71f4305511..072d9d0bfd3 100644 --- a/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java +++ b/tests/src/test/java/org/sonarqube/tests/user/UsersPageTest.java @@ -28,7 +28,6 @@ import org.junit.Rule; import org.junit.Test; import org.sonarqube.qa.util.Tester; import org.sonarqube.qa.util.pageobjects.UsersManagementPage; -import org.sonarqube.tests.Category1Suite; import org.sonarqube.ws.Users; import org.sonarqube.ws.Users.CreateWsResponse.User; import org.sonarqube.ws.client.users.GroupsRequest; @@ -42,7 +41,7 @@ public class UsersPageTest { private User adminUser; @ClassRule - public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; + public static Orchestrator orchestrator = UserSuite.ORCHESTRATOR; @Rule public UserRule userRule = UserRule.from(orchestrator);