diff options
author | Steve Marion <steve.marion@sonarsource.com> | 2025-03-18 11:36:37 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2025-03-18 20:04:07 +0000 |
commit | 5f27a59fa2d104ef3712fa72c65eca049ad54c8c (patch) | |
tree | b9c063e764a295664ef4a2060c1817cad8074fe6 | |
parent | 85a491c9de96fa53977c6335dae2263a70e961d5 (diff) | |
download | sonarqube-5f27a59fa2d104ef3712fa72c65eca049ad54c8c.tar.gz sonarqube-5f27a59fa2d104ef3712fa72c65eca049ad54c8c.zip |
SONAR-24616 add new dismissable notice for architecture visualization.
4 files changed, 94 insertions, 56 deletions
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CurrentActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CurrentActionIT.java index b2a716df087..f343d99f2b2 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CurrentActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/CurrentActionIT.java @@ -27,18 +27,18 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Suite; -import org.sonar.db.component.ComponentQualifiers; -import org.sonar.server.component.ComponentType; -import org.sonar.server.component.ComponentTypeTree; -import org.sonar.server.component.ComponentTypes; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.System2; import org.sonar.core.platform.PlatformEditionProvider; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentQualifiers; import org.sonar.db.property.PropertyDto; import org.sonar.db.user.UserDto; import org.sonar.server.common.avatar.AvatarResolverImpl; +import org.sonar.server.component.ComponentType; +import org.sonar.server.component.ComponentTypeTree; +import org.sonar.server.component.ComponentTypes; import org.sonar.server.permission.PermissionService; import org.sonar.server.permission.PermissionServiceImpl; import org.sonar.server.tester.UserSessionRule; @@ -55,7 +55,6 @@ import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFIL import static org.sonar.db.permission.GlobalPermission.PROVISION_PROJECTS; import static org.sonar.db.permission.GlobalPermission.SCAN; import static org.sonar.db.user.GroupTesting.newGroupDto; -import static org.sonar.server.user.ws.DismissNoticeAction.AVAILABLE_NOTICE_KEYS; import static org.sonar.test.JsonAssert.assertJson; @RunWith(Suite.class) @@ -262,7 +261,7 @@ public class CurrentActionIT { @Parameterized.Parameters public static Collection<String> parameterCombination() { - return AVAILABLE_NOTICE_KEYS; + return DismissNoticeAction.DismissNotices.getAvailableKeys(); } private final String notice; diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DismissNoticeActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DismissNoticeActionIT.java index a3c6748a49a..4d0c6acf8b5 100644 --- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DismissNoticeActionIT.java +++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/DismissNoticeActionIT.java @@ -20,12 +20,12 @@ package org.sonar.server.user.ws; import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.util.Optional; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.sonar.api.utils.System2; import org.sonar.db.DbTester; import org.sonar.db.property.PropertyDto; @@ -37,20 +37,18 @@ import org.sonar.server.ws.WsActionTester; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.sonar.server.user.ws.DismissNoticeAction.AVAILABLE_NOTICE_KEYS; -@RunWith(DataProviderRunner.class) -public class DismissNoticeActionIT { +class DismissNoticeActionIT { - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); - @Rule - public UserSessionRule userSessionRule = UserSessionRule.standalone(); + @RegisterExtension + private DbTester db = DbTester.create(System2.INSTANCE); + @RegisterExtension + private UserSessionRule userSessionRule = UserSessionRule.standalone(); private final WsActionTester tester = new WsActionTester(new DismissNoticeAction(userSessionRule, db.getDbClient())); @Test - public void authentication_is_required() { + void authentication_is_required() { TestRequest testRequest = tester.newRequest() .setParam("notice", "anyValue"); @@ -60,7 +58,7 @@ public class DismissNoticeActionIT { } @Test - public void notice_parameter_is_mandatory() { + void notice_parameter_is_mandatory() { userSessionRule.logIn(); TestRequest testRequest = tester.newRequest(); @@ -70,20 +68,19 @@ public class DismissNoticeActionIT { } @Test - public void notice_not_supported() { + void notice_not_supported() { userSessionRule.logIn(); TestRequest testRequest = tester.newRequest() .setParam("notice", "not_supported_value"); assertThatThrownBy(testRequest::execute) .isInstanceOf(IllegalArgumentException.class) - .hasMessage( - "Value of parameter 'notice' (not_supported_value) must be one of: [educationPrinciples, sonarlintAd, issueCleanCodeGuide, qualityGateCaYCConditionsSimplification, " + - "overviewZeroNewIssuesSimplification, issueNewIssueStatusAndTransitionGuide, onboardingDismissCaycBranchSummaryGuide, showNewModesTour, showNewModesBanner]"); + .hasMessageStartingWith( + "Value of parameter 'notice' (not_supported_value) must be one of: ["); } @Test - public void notice_already_exist_dont_fail() { + void notice_already_exist_dont_fail() { userSessionRule.logIn(); PropertyDto property = new PropertyDto().setKey("user.dismissedNotices.educationPrinciples").setUserUuid(userSessionRule.getUuid()); db.properties().insertProperties(userSessionRule.getLogin(), null, null, null, property); @@ -97,9 +94,9 @@ public class DismissNoticeActionIT { assertThat(db.properties().findFirstUserProperty(userSessionRule.getUuid(), "user.dismissedNotices.educationPrinciples")).isPresent(); } - @Test - @UseDataProvider("noticeKeys") - public void dismiss_notice(String noticeKey) { + @ParameterizedTest + @MethodSource("noticeKeys") + void dismiss_notice(String noticeKey) { userSessionRule.logIn(); TestResponse testResponse = tester.newRequest() @@ -113,9 +110,7 @@ public class DismissNoticeActionIT { } @DataProvider - public static Object[][] noticeKeys() { - return AVAILABLE_NOTICE_KEYS.stream() - .map(noticeKey -> new Object[] {noticeKey}) - .toArray(Object[][]::new); + static Set<String> noticeKeys() { + return DismissNoticeAction.DismissNotices.getAvailableKeys(); } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CurrentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CurrentAction.java index 36a5c376f48..aabb5ff63a4 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CurrentAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/CurrentAction.java @@ -49,7 +49,6 @@ import static java.util.Optional.of; import static java.util.Optional.ofNullable; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.sonar.api.web.UserRole.USER; -import static org.sonar.server.user.ws.DismissNoticeAction.AVAILABLE_NOTICE_KEYS; import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.APPLICATION; import static org.sonarqube.ws.Users.CurrentWsResponse.HomepageType.PORTFOLIO; @@ -124,7 +123,8 @@ public class CurrentAction implements UsersWsAction { .setHomepage(buildHomepage(dbSession, user)) .setUsingSonarLintConnectedMode(user.getLastSonarlintConnectionDate() != null); - AVAILABLE_NOTICE_KEYS.forEach(key -> builder.putDismissedNotices(key, isNoticeDismissed(user, key))); + DismissNoticeAction.DismissNotices.getAvailableKeys() + .forEach(key -> builder.putDismissedNotices(key, isNoticeDismissed(user, key))); ofNullable(emptyToNull(user.getEmail())).ifPresent(builder::setEmail); ofNullable(emptyToNull(user.getEmail())).ifPresent(u -> builder.setAvatar(avatarResolver.create(user))); diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/DismissNoticeAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/DismissNoticeAction.java index 7a779e06308..407ffcf2f36 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/DismissNoticeAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/DismissNoticeAction.java @@ -19,7 +19,9 @@ */ package org.sonar.server.user.ws; -import java.util.List; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -31,23 +33,52 @@ import org.sonar.db.property.PropertyQuery; import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkState; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.EDUCATION_PRINCIPLES; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.ISSUE_CLEAN_CODE_GUIDE; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.SHOW_DNA_BANNER; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.SHOW_DNA_OPTIN_BANNER; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.SHOW_DNA_TOUR; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.SHOW_NEW_MODES_BANNER; +import static org.sonar.server.user.ws.DismissNoticeAction.DismissNotices.SHOW_NEW_MODES_TOUR; public class DismissNoticeAction implements UsersWsAction { - private static final String EDUCATION_PRINCIPLES = "educationPrinciples"; - private static final String SONARLINT_AD = "sonarlintAd"; - private static final String ISSUE_CLEAN_CODE_GUIDE = "issueCleanCodeGuide"; - private static final String QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION = "qualityGateCaYCConditionsSimplification"; - private static final String OVERVIEW_ZERO_NEW_ISSUES_SIMPLIFICATION = "overviewZeroNewIssuesSimplification"; - private static final String ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE = "issueNewIssueStatusAndTransitionGuide"; - private static final String ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE = "onboardingDismissCaycBranchSummaryGuide"; - private static final String SHOW_NEW_MODES_TOUR = "showNewModesTour"; - private static final String SHOW_NEW_MODES_BANNER = "showNewModesBanner"; - - protected static final List<String> AVAILABLE_NOTICE_KEYS = List.of(EDUCATION_PRINCIPLES, SONARLINT_AD, ISSUE_CLEAN_CODE_GUIDE, QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION, - OVERVIEW_ZERO_NEW_ISSUES_SIMPLIFICATION, ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE, ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE, SHOW_NEW_MODES_TOUR, SHOW_NEW_MODES_BANNER); + public enum DismissNotices { + EDUCATION_PRINCIPLES("educationPrinciples"), + SONARLINT_AD("sonarlintAd"), + ISSUE_CLEAN_CODE_GUIDE("issueCleanCodeGuide"), + QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION("qualityGateCaYCConditionsSimplification"), + OVERVIEW_ZERO_NEW_ISSUES_SIMPLIFICATION("overviewZeroNewIssuesSimplification"), + ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE("issueNewIssueStatusAndTransitionGuide"), + ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE("onboardingDismissCaycBranchSummaryGuide"), + SHOW_NEW_MODES_TOUR("showNewModesTour"), + SHOW_NEW_MODES_BANNER("showNewModesBanner"), + SHOW_DNA_OPTIN_BANNER("showDesignAndArchitectureOptInBanner"), + SHOW_DNA_BANNER("showDesignAndArchitectureBanner"), + SHOW_DNA_TOUR("showDesignAndArchitectureTour"), + ; + + private final String key; + + DismissNotices(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public static Set<String> getAvailableKeys() { + return Arrays.stream(values()) + .map(DismissNotices::getKey) + .collect(Collectors.toSet()); + } + } public static final String USER_DISMISS_CONSTANT = "user.dismissedNotices."; - public static final String SUPPORT_FOR_NEW_NOTICE_MESSAGE = "Support for new notice '%s' was added."; + private static final String SUPPORT_FOR_NEW_NOTICE_MESSAGE = "Support for new notice '%s' was added."; private final UserSession userSession; private final DbClient dbClient; @@ -57,16 +88,29 @@ public class DismissNoticeAction implements UsersWsAction { this.dbClient = dbClient; } + private static String printNewNotice(DismissNotices notice) { + return SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(notice.getKey()); + } + + private static String printNewNotice(DismissNotices... notices) { + String noticesList = Arrays.stream(notices) + .map(DismissNotices::getKey) + .collect(Collectors.joining(", ")); + return SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(noticesList); + } + + @Override public void define(WebService.NewController context) { WebService.NewAction action = context.createAction("dismiss_notice") .setDescription("Dismiss a notice for the current user. Silently ignore if the notice is already dismissed.") - .setChangelog(new Change("10.8", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(SHOW_NEW_MODES_TOUR))) - .setChangelog(new Change("10.8", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(SHOW_NEW_MODES_BANNER))) - .setChangelog(new Change("10.6", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE))) - .setChangelog(new Change("10.4", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE))) - .setChangelog(new Change("10.3", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION))) - .setChangelog(new Change("10.2", SUPPORT_FOR_NEW_NOTICE_MESSAGE.formatted(ISSUE_CLEAN_CODE_GUIDE))) + .setChangelog(new Change("25.4", printNewNotice(SHOW_DNA_OPTIN_BANNER, SHOW_DNA_BANNER, SHOW_DNA_TOUR))) + .setChangelog(new Change("10.8", printNewNotice(SHOW_NEW_MODES_TOUR))) + .setChangelog(new Change("10.8", printNewNotice(SHOW_NEW_MODES_BANNER))) + .setChangelog(new Change("10.6", printNewNotice(ONBOARDING_CAYC_BRANCH_SUMMARY_GUIDE))) + .setChangelog(new Change("10.4", printNewNotice(ISSUE_NEW_ISSUE_STATUS_AND_TRANSITION_GUIDE))) + .setChangelog(new Change("10.3", printNewNotice(QUALITY_GATE_CAYC_CONDITIONS_SIMPLIFICATION))) + .setChangelog(new Change("10.2", printNewNotice(ISSUE_CLEAN_CODE_GUIDE))) .setSince("9.6") .setInternal(true) .setHandler(this) @@ -75,7 +119,7 @@ public class DismissNoticeAction implements UsersWsAction { action.createParam("notice") .setDescription("notice key to dismiss") .setExampleValue(EDUCATION_PRINCIPLES) - .setPossibleValues(AVAILABLE_NOTICE_KEYS); + .setPossibleValues(DismissNotices.getAvailableKeys()); } @Override @@ -89,7 +133,7 @@ public class DismissNoticeAction implements UsersWsAction { dismissNotice(response, currentUserUuid, noticeKeyParam); } - public void dismissNotice(Response response, String currentUserUuid, String noticeKeyParam) { + private void dismissNotice(Response response, String currentUserUuid, String noticeKeyParam) { try (DbSession dbSession = dbClient.openSession(false)) { String paramKey = USER_DISMISS_CONSTANT + noticeKeyParam; PropertyQuery query = new PropertyQuery.Builder() |